canvas基礎學習筆記(五)

canvas高級內容

一、陰影

context.shadowColor="gray";//指定陰影的顏色
context.shadowOffsetX=-20;//指定陰影的位移值
context.shadowOffsetY=-20;//指定陰影的位移值
context.shadowBlur=5;//描述陰影模糊的程度(值越大越模糊)
示例代碼如下:

<script type="text/javascript">
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=1024;
       canvas.height=800;
    
       var context=canvas.getContext('2d');
       
       context.fillStyle="#058";
       context.shadowColor="gray";//可以使用任意的css可以接受的樣式值,包括使用rgba設置半透明色
       //context.shadowOffsetX=20;
       //context.shadowOffsetY=20;
       //負值時陰影方向會相反
       context.shadowOffsetX=-20;
       context.shadowOffsetY=-20;
       context.shadowBlur=5;//越大越模糊

       context.fillRect(200,200,400,400);
      }
</script>

二、global屬性

1.globalAlpha

context.globalAlpha=1;默認值,在這種情況下默認繪制的圖形都不具有透明度,即后繪制的圖形會蓋住之前繪制的圖形。示例如下:

<script type="text/javascript">
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=1200;
       canvas.height=700;
    
       var context=canvas.getContext('2d');

       context.globalAlpha=0.5;//不加此句時后繪制的圓會蓋住之前繪制的
       //畫出100個圓
       for(var i=0;i<100;i++){
        var R=Math.floor(Math.random()*255);
        var G=Math.floor(Math.random()*255);
        var B=Math.floor(Math.random()*255);

        context.fillStyle="rgb("+R+","+G+","+B+")";

        context.beginPath();
        context.arc(Math.random()*canvas.width,Math.random()*canvas.height,Math.random()*100,0,Math.PI*2);
        context.fill();
       }
      }
</script>

2.globalCompositeOperation(描述繪制的圖形在重疊時所產生的效果)

context.globalCompositeOperation="source-over";//后繪制的圖形會蓋住之前繪制的圖形
context.globalCompositeOperation="destination-over";//之前繪制的圖形會蓋住之后繪制的圖形
示例如下:

<script type="text/javascript">
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=800;
       canvas.height=800;
    
       var context=canvas.getContext('2d');

      context.fillStyle="blue";
      context.fillRect(100,200,400,400);

      //context.globalCompositeOperation="source-over";
      context.globalCompositeOperation="destination-over";
      context.fillStyle="red";

      context.beginPath();
      context.moveTo(400,300);
      context.lineTo(650,700);
      context.lineTo(150,700);
      context.closePath();
      context.fill();
  }
</script>

此外,其他globalCompositeOperation屬性的屬性值如下:
source-over、source-atop、source-in 、source-out ;destination-over 、destination-atop 、destination-in 、destination-out;lighter、 copy、 xor。示例代碼如下:

<body >
 <canvas id="canvas" style="border: 1px solid #aaa;display: block;margin: 50px auto">
 當前瀏覽器不支持canvas,請更換瀏覽器后再試
 </canvas>
 <div id="buttons">
   <a href="#">source-over</a>
   <a href="#">source-atop</a>
   <a href="#">source-in</a>
   <a href="#">source-out</a>
   <a href="#">destination-over</a>
   <a href="#">destination-atop</a>
   <a href="#">destination-in</a>
   <a href="#">destination-out</a>
   <a href="#">lighter</a>
   <a href="#">copy</a>
   <a href="#">xor</a>
 </div>

<script type="text/javascript">
  window.onload=function(){
    draw("source-over");
    var buttons=document.getElementById("buttons").getElementsByTagName("a");
    for(var i=0;i<buttons.length;i++){
      buttons[i].onclick=function(){
        draw(this.text);
        return false;
      }
    }
  }

    function draw(compositeStyle){
      var canvas=document.getElementById('canvas');
      canvas.width=1200;
      canvas.height=800;
      var context=canvas.getContext('2d');

      context.clearRect(0,0, canvas.width,canvas.height);

      //draw title
      context.font="bold 40px Arial";
      context.textAlign="center";
      context.textBaseline="middle";
      context.fillStyle="#058";
      context.fillText("globalCompositeOperation="+compositeStyle,canvas.width/2,60);

      //draw a rect
      context.fillStyle="blue";
      context.fillRect(300,150,500,500);

      //drae a triangle
      context.globalCompositeOperation=compositeStyle;
      context.fillStyle="red";
      context.beginPath();
      context.moveTo(700,250);
      context.lineTo(1000,750);
      context.lineTo(400,750);
      context.closePath();
      context.fill();
  }
</script>

三、clip和剪輯區域

1. context.clip();此函數與路徑規劃函數一起使用,例如:lineTo、arc、貝塞爾曲線等等。示例代碼如下:

<script type="text/javascript">
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=800;
       canvas.height=800;
    
       var context=canvas.getContext('2d');
       //設置畫布顏色
       context.beginPath();
       context.fillStyle="black";
       context.fillRect(0,0,canvas.width,canvas.height)

       context.beginPath();
       context.arc(400,400,150,0,Math.PI*2);
       context.fillStyle="#fff";
       context.fill();
       context.clip();
       
       context.font="bold 140px Arial";
       context.textAlign="center";
       context.textBaseline="middle";
       context.fillStyle="#058";
       context.fillText("CANVAS",canvas.width/2,canvas.height/2);    
  }
</script>

2.小實例(圓形探照燈制作)

<script type="text/javascript">
  var searchLight={x:400,y:400,radius:150,vx:Math.random()*5+10,vy:Math.random()*5+10,}//vx vy代表移動的速度

    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=800;
       canvas.height=800;
    
       var context=canvas.getContext('2d');
       
       //動畫基礎
       setInterval(function(){
        draw(context);
        update(canvas.width,canvas.height);
       },40);
    }

    function draw(cxt){
      var canvas=cxt.canvas;
      cxt.clearRect(0,0,canvas.width,canvas.height);//清空畫布

      cxt.save();
      //填充畫布為黑色
      cxt.beginPath();
      cxt.fillStyle="black";
      cxt.fillRect(0,0,canvas.width,canvas.height);
      //畫出填充區域
      cxt.beginPath();
      cxt.arc(searchLight.x,searchLight.y,searchLight.radius,0,Math.PI*2);
      cxt.fillStyle="#fff";
      cxt.fill();
      cxt.clip();
      //撰寫文字
      cxt.font="bold 140px Arial";
      cxt.textAlign="center";
      cxt.textBaseline="middle";
      cxt.fillStyle="#058";
      cxt.fillText("CANVAS",canvas.width/2,canvas.height/4);
      cxt.fillText("CANVAS",canvas.width/2,canvas.height/2);
      cxt.fillText("CANVAS",canvas.width/2,canvas.height*3/4);

      cxt.restore();
    }

    function update(canvasWidth,canvasHeight){
      searchLight.x+=-searchLight.vx;
      searchLight.y+=searchLight.vy;

      if(searchLight.x-searchLight.radius<=0){
        searchLight.vx=-searchLight.vx;
        searchLight.x=searchLight.radius;
      }

      if(searchLight.x+searchLight.radius>=canvasWidth){
        searchLight.vx=-searchLight.vx;
        searchLight.x=canvasWidth-searchLight.radius;
      }
      
      if(searchLight.y-searchLight.radius<=0){
        searchLight.vy=-searchLight.vy;
        searchLight.y=searchLight.radius;
      }
      
       if(searchLight.y+searchLight.radius>=canvasHeight){
        searchLight.vy=-searchLight.vy;
        searchLight.y=canvasHeight-searchLight.radius;
      }
    }
</script>

四、路徑方向和剪紙效果

1.路徑方向(非零環繞原則)

路徑示意圖.jpg

如上圖,將圖形的繪制路徑首尾相接并標明方向,然后從某個區域由區域內到外畫出一個箭頭,兩個箭頭方向相加不為0則染色,為0則不染色。下面以一個圓環的繪制為例:

圓環路徑示意圖.jpg

示例代碼如下:

<script type="text/javascript">
 
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=800;
       canvas.height=800;
    
       var context=canvas.getContext('2d');
       
       //繪制圓環
       context.beginPath();
       context.arc(400,400,300,0,Math.PI*2,false);
       context.arc(400,400,150,0,Math.PI*2,true);
       context.closePath();

       context.fillStyle="#058";
       context.shadowColor="gray";
       context.shadowOffsetX=10;
       context.shadowOffsetY=10;
       context.shadowBlur=10;
       context.fill();
    }
</script>

2.剪紙效果(需明確哪個位置染色,哪個位置不染色)

示例代碼如下:

<script type="text/javascript">
 
    window.onload=function(){
       var canvas=document.getElementById('canvas');
      
       canvas.width=800;
       canvas.height=800;
    
       var context=canvas.getContext('2d');
       
       //繪制
       context.beginPath();
       context.rect(100,100,600,600);//順時針
       pathRect(context,200,200,400,200);//逆時針
       pathTriangle(context,300,450,150,650,450,650);
       context.arc(550,550,100,0,Math.PI*2,true);//逆時針
       context.closePath();

       context.fillStyle="#058";
       context.shadowColor="gray";
       context.shadowOffsetX=10;
       context.shadowOffsetY=10;
       context.shadowBlur=10;
       context.fill();
    }
  
  function pathRect(cxt,x,y,width,height){
    cxt.moveTo(x,y);
    cxt.lineTo(x,y+height);
    cxt.lineTo(x+width,y+height);
    cxt.lineTo(x+width,y);
    cxt.lineTo(x,y);
  }
  function pathTriangle(cxt,x1,y1,x2,y2,x3,y3){
    cxt.moveTo(x1,y1);
    cxt.lineTo(x2,y2);
    cxt.lineTo(x3,y3);
    cxt.lineTo(x1,y1);
  }
</script>

五、使用canvas交互

isPointInPath 是canvas中內置的點擊檢測函數
context.isPointInPath(x,y)看傳入的點(x,y)是否在當前規劃的路徑內。下邊的例子是繪制10個小球,當點擊小球時它的顏色由藍色變為紅色,示例代碼如下:

<script type="text/javascript">
  var balls=[];
  var canvas=document.getElementById('canvas');
  var context=canvas.getContext('2d');

    window.onload=function(){
    canvas.width=800;
    canvas.height=800;
    for(var i=0;i<10;i++){
      var aBall={x:Math.random()*canvas.width,
          y:Math.random()*canvas.height,
          r:Math.random()*50+20};
          balls[i]=aBall;
    }
    draw();
    canvas.addEventListener("mouseup",detect);//用canvas的addEventListener方法創建事件
  }

    function draw(){
      //一次for循環遍歷balls數組
      for(var i=0;i<balls.length;i++){
        context.beginPath();
        context.arc(balls[i].x,balls[i].y,balls[i].r,0,Math.PI*2);

        context.fillStyle="#058";
        context.fill();
      }
    }

    function detect(event){
      //獲得鼠標點擊在canvas中位置的方法
      var x=event.clientX-canvas.getBoundingClientRect().left;//鼠標坐標基于Web文檔的橫向距離減去canvas畫布離整個文檔左側的距離
      var y=event.clientY-canvas.getBoundingClientRect().top;

      for(var i=0;i<balls.length;i++){
        context.beginPath();
        context.arc(balls[i].x,balls[i].y,balls[i].r,0,Math.PI*2);

        if(context.isPointInPath(x,y)){
          context.fillStyle="red";
          context.fill();
        }
      }
    }
</script>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容