1. 程式人生 > >高程3總結#第15章使用Canvas繪圖

高程3總結#第15章使用Canvas繪圖

使用Canvas繪圖

基本用法

  • 要使用<canvas>元素,必須先設定其width和height屬性,指定可以繪圖的區域大小。出現在開始和結束標籤中的內容是後備資訊,如果瀏覽器不支援<canvas>元素,就會顯示這些資訊

    <canvas id="drawing" width="200" height="200">A drawing of something</canvas>
  • 要在這塊畫布上繪圖,需要取得繪圖上下文,而取得繪圖上下文物件的引用,需要呼叫getContext()方法並傳入上下文的名字,傳入"2d",就可以取得2D上下文的物件

    var drawing=document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if(drawing.getContext){
      var context=drawing.getContext("2d");
      //更多程式碼
    }
  • 在使用<canvas>元素之前,首先要檢測getContext()方法是否存在

    var drawing=document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if(drawing.getContext){
      //取得影象的資料URI
      var imgURI=drawing.toDataURL("image/png");
      //顯示影象
      var image=document.createElement("img");
      image.src=imgURI;
      document.body.appendChild(image);
    }

2D上下文

  • 2D上下文的座標開始於<canvas>元素的左上角,原點座標是(0,0)。所有座標的值都基於這個原點計算,x值越大表示越靠右,y值越大表示越靠下。預設情況下,width和height表示水平和垂直兩個方向上可用的畫素數目

填充和描邊

  • 操作得結果取決於兩個屬性,fillStyle和strokeStyle
  • 這兩個屬性的值可以是字串,漸變物件或模擬物件,而且它們的預設值都是"#000000"

    var drawing=document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if(drawing.getContext){
      var content=drawing.getContext("2d");
      context.strokeStyle="red";
      context.fillStyle="#0000ff"
    }

繪製矩形

  • 與矩形相關的方法包括fillRect()、strokeRect()、clearRect()三個方法接收4個引數,矩形的x座標、矩形的y座標、矩形的寬度和矩形的高度。這些引數的單位都是畫素

    • fillRect()方法在畫布上繪製的矩形會填充指定的顏色

      var drawing = document.getElementById("drawing");
      //確定瀏覽器支援<canvas>元素
      if (drawing.getContext){
        var context = drawing.getContext("2d");
        // 繪製紅色矩形
        context.fillStyle = "#ff0000";
        context.fillRect(10, 10, 50, 50);
        // 繪製半透明的藍色矩形
        context.fillStyle = "rgba(0,0,255,0.5)";
        context.fillRect(30, 30, 50, 50);
      }
    • strokeRect()方法在畫布上繪製的矩形會使用指定的顏色描邊,描邊顏色通過strokeStyle屬性指定

      var drawing=document.getElementById("drawing");
      //確定瀏覽器支援<canvas>元素
      if(drawing.getContext){
        var context=drawing.getContext("2d");
        //繪製紅色描邊矩形
        context.strokeStyle="#ff0000";
        context.strokeRect(10,10,50,50);
        //繪製半透明的藍色描邊矩形
        context.strokeStyle="rgba(0,0,255,0.5)";
        context.strokeRect(30,30,50,50)
      }
    • clearRect()方法用於清除畫布上的矩形區域,本質上,這個方法可以把繪製上下文中的某一矩形區域變透明

      var drawing = document.getElementById("drawing");
      //確定瀏覽器支援<canvas>元素
      if (drawing.getContext){
        var context = drawing.getContext("2d");
        //繪製紅色矩形
        context.fillStyle = "#ff0000";
        context.fillRect(10, 10, 50, 50);
        //繪製半透明的藍色矩形
        context.fillStyle = "rgba(0,0,255,0.5)";
        context.fillRect(30, 30, 50, 50);
        // 在兩個矩形重疊的地方清除一個小矩形
        context.clearRect(40, 40, 10, 10);
      }

繪製路徑

  • 要繪製路徑,首先必須呼叫beginPath()方法,表示要開始繪製的新路徑

    • arc(x, y, radius, startAngle, endAngle, counterclockwise),以 (x,y) 為圓心繪製一條弧線,弧線半徑為 radius ,起始和結束角度(用弧度表示)分別為 startAngle 和endAngle 。最後一個引數表示 startAngle 和 endAngle 是否按逆時針方向計算,值為 false表示按順時針方向計算。
    • arcTo(x1, y1, x2, y2, radius),從上一點開始繪製一條弧線,到 (x2,y2) 為止,並且以給定的半徑 radius 穿過 (x1,y1) 。
    • bezierCurveTo(c1x, c1y, c2x, c2y, x, y),從上一點開始繪製一條曲線,到 (x,y) 為止,並且以 (c1x,c1y) 和 (c2x,c2y) 為控制點。
    • lineTo(x, y),從上一點開始繪製一條直線,到 (x,y) 為止。
    • moveTo(x, y),將繪圖遊標移動到 (x,y) ,不畫線。
    • quadraticCurveTo(cx, cy, x, y),從上一點開始繪製一條二次曲線,到 (x,y) 為止,並且以 (cx,cy) 作為控制點。
    • rect(x, y, width, height),從點 (x,y) 開始繪製一個矩形,寬度和高度分別由 width 和height 指定。這個方法繪製的是矩形路徑,而不是 strokeRect() 和 fillRect() 所繪製的獨立的形狀。
    var drawing = document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if (drawing.getContext){
      var context = drawing.getContext("2d");
      // 開始路徑
      context.beginPath();
      // 繪製外圓
      context.arc(100, 100, 99, 0, 2 * Math.PI, false);
      // 繪製內圓
      context.moveTo(194, 100);
      context.arc(100, 100, 94, 0, 2 * Math.PI, false);
      // 繪製分針
      context.moveTo(100, 100);
      context.lineTo(100, 15);
      // 繪製時針
      context.moveTo(100, 100);
      context.lineTo(35, 100);
      // 描邊路徑
      context.stroke();
    }

繪製文字

  • 繪製文字主要兩個方法:fillText()和strokeText()。這兩個方法都可以接收4個引數:要繪製的文字字串、x座標、y座標和可選的最大畫素寬度
  • 這兩個方法以3個屬性為基礎

    • font,表示文字樣式、大小及字型,用 CSS 中指定字型的格式來指定,例如 "10px Arial" 。
    • textAlign,表示文字對齊方式。可能的值有 "start" 、 "end" 、 "left" 、 "right" 和 "center" 。建議使用 "start" 和 "end" ,不要使用 "left" 和 "right" ,因為前兩者的意思更穩妥,能同時適合從左到右和從右到左顯示(閱讀)的語言。
    • textBaseline,表示文字的基線。可能的值有 "top" 、 "hanging" 、 "middle" 、 "alphabetic" 、"ideographic" 和 "bottom" 。
    //正常
    context.font = "bold 14px Arial";
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.fillText("12", 100, 20);
    // 起點對齊
    context.textAlign = "start";
    context.fi llText("12", 100, 40);
    // 終點對齊
    context.textAlign = "end";
    context.fi llText("12", 100, 60);

變換

  • 修改變換矩陣

    • rotate(angle),圍繞原點旋轉影象 angle 弧度。
    • scale(scaleX, scaleY),縮放影象,在 x 方向乘以 scaleX ,在 y 方向乘以 scaleY 。 scaleX和 scaleY 的預設值都是 1.0。
    • translate(x, y),將座標原點移動到 (x,y) 。執行這個變換之後,座標(0,0)會變成之前由 (x,y)表示的點。
    • transform(m1_1, m1_2, m2_1, m2_2, dx, dy),直接修改變換矩陣,方式是乘以如下矩陣。m1_1 m1_2 dxm2_1 m2_2 dy0 0 1
    • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy),將變換矩陣重置為預設狀態,然後再呼叫 transform()
    var drawing = document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if (drawing.getContext){
      var context = drawing.getContext("2d");
      //開始路徑
      context.beginPath();
      //繪製外圓
      context.arc(100, 100, 99, 0, 2 * Math.PI, false);
      //繪製內圓
      context.moveTo(194, 100);
      context.arc(100, 100, 94, 0, 2 * Math.PI, false);
      //變換原點
      context.translate(100, 100);
      // 旋轉錶針
      context.rotate(1);
      //繪製分針
      context.moveTo(0,0);
      context.lineTo(0, -85);
      //繪製時針
      context.moveTo(0, 0);
      context.lineTo(-65, 0);
      //描邊路徑
      context.stroke();
    }

繪製圖像

  • 使用drawImage()將影象繪製到畫布上,三種不同的引數組合

    • 3個引數:傳入HTML<img>元素,繪製圖像的起點的x和y座標
    • 5個引數:3個引數+目標寬度和目標高度
    • 9個引數:要繪製的影象,源影象的x座標,源影象的y座標,源影象的寬度,源影象的高度,目標影象的x座標,目標影象的y座標,目標影象的寬度,目標影象的高度

陰影

  • 2D上下文根據屬性值自動繪製陰影

    • shadowColor,用 CSS 顏色格式表示的陰影顏色,預設為黑色。
    • shadowOffsetX,形狀或路徑 x 軸方向的陰影偏移量,預設為 0。
    • shadowOffsetY,形狀或路徑 y 軸方向的陰影偏移量,預設為 0。
    • shadowBlur,模糊的畫素數,預設 0,即不模糊。
    var context = drawing.getContext("2d");
    // 設定陰影
    context.shadowOffsetX = 5;
    context.shadowOffsetY = 5;
    context.shadowBlur = 4;
    context.shadowColor = "rgba(0, 0, 0, 0.5)";
    //繪製紅色矩形
    context.fillStyle = "#ff0000";
    context.fillRect(10, 10, 50, 50);
    //繪製藍色矩形
    context.fillStyle = "rgba(0,0,255,1)";
    context.fillRect(30, 30, 50, 50);

漸變

  • 要建立一個新的線性漸變,可以呼叫createLinearGradient()方法,這個方法接收4個引數:起點的x座標、起點的y座標、終點的x座標、終點的y座標

    //繪製紅色矩形
    context.fillStyle="#ff0000";
    context.fillRect(10,10,50,50);
    //繪製漸變矩形
    context.fillStyle=gradient;
    context.fillRect(30,30,50,50);

模式

var image=document.images[0],
  pattern=context.createPattern(image,"repeat");
//繪製矩形
context.fillStyle=pattern;
context.fillRect(10,10,150,150);

使用影象資料

  • getImageData()取得原始影象資料,這個方法接收4個引數:要取得其資料的畫面區域的x和y座標以及該區域的畫素寬度和高度

    var drawing = document.getElementById("drawing");
    //確定瀏覽器支援<canvas>元素
    if (drawing.getContext){
      var context = drawing.getContext("2d"),
          image = document.images[0],
          imageData, data,
          i, len, average,
          red, green, blue, alpha;
      //繪製原始影象
      context.drawImage(image, 0, 0);
      //取得影象資料
      imageData = context.getImageData(0, 0, image.width, image.height);
      data = imageData.data;
      for (i=0, len=data.length; i < len; i+=4){
        red = data[i];
        green = data[i+1];
        blue = data[i+2];
        alpha = data[i+3];
        //求得 rgb 平均值
        average = Math.floor((red + green + blue) / 3);
        //設定顏色值,透明度不變
        data[i] = average;
        data[i+1] = average;
        data[i+2] = average;
      }
      //回寫影象資料並顯示結果
      imageData.data = data;
      context.putImageData(imageData, 0, 0);
    }

合成

  • 應用到2D上下文所有繪製操作得屬性。globalAlpha和globalCompositionOperation

    • globalAlpha是一個介於0和1之間的值,用於指定所有繪製的透明度,預設值為0,如果所有後續操作都要基於相同的透明度,就可以先把globalAlpha設定為適當值,然後繪製,最後再把它設定回預設值0

      //繪製紅色矩形
      context.fillStyle = "#ff0000";
      context.fillRect(10, 10, 50, 50);
      //修改全域性透明度
      context.globalAlpha = 0.5;
      //繪製藍色矩形
      context.fillStyle = "rgba(0,0,255,1)";
      context.fillRect(30, 30, 50, 50);
      //重置全域性透明度
      context.globalAlpha = 0
    • globalCompositionOperation表示繪製的圖形怎樣與先繪製的圖形結合,這個屬性的值是字串

      • source-over預設值,後繪製的圖形位於先繪製的圖形上方。
      • source-in,後繪製的圖形與先繪製的圖形重疊的部分可見,兩者其他部分完全透明。
      • source-out,後繪製的圖形與先繪製的圖形不重疊的部分可見,先繪製的圖形完全透明。
      • source-atop,後繪製的圖形與先繪製的圖形重疊的部分可見,先繪製圖形不受影響。
      • destination-over,後繪製的圖形位於先繪製的圖形下方,只有之前透明畫素下的部分才可見。
      • destination-in,後繪製的圖形位於先繪製的圖形下方,兩者不重疊的部分完全透明。
      • destination-out,後繪製的圖形擦除與先繪製的圖形重疊的部分。
      • destination-atop,後繪製的圖形位於先繪製的圖形下方,在兩者不重疊的地方,先繪製的圖形會變透明。
      • lighter,後繪製的圖形與先繪製的圖形重疊部分的值相加,使該部分變亮。
      • copy,後繪製的圖形完全替代與之重疊的先繪製圖形。
      • xor,後繪製的圖形與先繪製的圖形重疊的部分執行“異或”操作。

WebGL

型別化陣列

  • 型別化陣列也是陣列,只不過其元素被設定為特定型別的值
  • 型別化陣列的核心就是一個名為ArrayBuffer的型別。

WebGL上下文

支援

  • Firefox 4+和 Chrome 都實現了 WebGL API。Safari 5.1 也實現了 WebGL,但預設是禁用的。