Canvas教程


一.Canvas基本用法

canvas對應中文是“畫布”,<canvas>是HTML5的新元素,IE9+支持

canvas元素的默認大小是300px * 150px,最簡單的代碼將生成一個透明的矩形畫布,例如:

<canvas>
  瀏覽器不支持canvas
</canvas>

如果瀏覽器支持的話,那么你將不會看到一個300px * 150px的透明塊(因為透明了嘛,審查元素就找到它了)。如果瀏覽器不支持,那么將會顯示替換文字:“瀏覽器不支持canvas”,例如IE8。

有了畫布,我好想畫點兒什么。不過對於canvas來說,最容易的是畫個空心/實心矩形,而不是畫條直線,例如:

<canvas id="my_canvas"> 瀏覽器不支持canvas </canvas>
<script type="text/javascript">
  var canvas = document.getElementById('my_canvas');
  if(canvas.getContext){
  var ctx = canvas.getContext('2d');//獲取2d上下文
  ctx.strokeStyle = '#f00';//邊框設置為紅色
  ctx.lineWidth = 3;//線寬設置為3px
  ctx.fillStyle = 'rgba(0, 0, 255, 0.5)';//填充半透明藍色
  ctx.strokeRect(0, 0, 50, 50);//描邊
  ctx.fillRect(0, 0, 50, 50);//填充
  }
</script>

結果就是這個樣子:

繪圖結果

二.畫方畫圓畫線

矩形在上面已經畫過了,用到了上下文對象的描邊和填充方法,除此之外還有一個關於矩形的方法:clearRect()參數意義相同,作用是掏空一個矩形塊(用透明色填充指定區域)

畫圓相對麻煩一點,比如要畫一個圓心為(30, 30)半徑為20的圓:

ctx.beginPath();//創建路徑
ctx.arc(30,30,20,0,Math.PI*2,true);//設置弧線路徑
ctx.closePath();//閉合路徑
ctx.stroke();//描邊
ctx.fill();//填充

arc(x, y, radius, startAngle, endAngle, counterclockwise)方法是用來畫弧線的,表示以(x, y)為圓心,radius為半徑,起始角度和結束角度分別為startAngle和endAngle,最后一個參數表示前兩個角度值是按順時針還是逆時針算,false表示順時針。

畫線比畫圓要簡單些(從(30, 30)畫一條50px的橫線):

ctx.beginPath();//創建路徑
ctx.moveTo(30, 30);//把起點移動到(30, 30)
ctx.lineTo(80, 30);//設置路徑連接兩點
ctx.closePath();//閉合路徑
ctx.stroke();//繪制

能畫線畫弧了,那畫三角五角也就不在話下了,除了上面用到的路徑方法之外,還有以下方法:

  • arcTo(x1, y1, x2, y2, radius):從上一點開始繪制一條弧線,到(x2, y2)為止,並且以給定的半徑radius穿過(x1, y1)

  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):貝塞爾曲線,從上一點開始繪制一條曲線,到(x, y)為止,並且以(c1x, c1y)和(c2x, c2y)為控制點

  • quadraticCurveTo(cx, cy, x, y):二次貝塞爾曲線,從上一點開始繪制一條二次曲線,到(x, y)為止,並且以(cx, cy)為控制點

  • rect(x, y, width, height):繪制矩形路徑

設置好路徑之后,可以用fill()方法填充或者用stroke()方法描邊,還可以用clip()方法對下面的繪圖作以限制(相當於PS的選區,詳情參見W3School

三.畫圖片

這個功能無疑是最重要的,簡單的圖形繪制並不是很實用(不信你拿坐標畫個肖像畫試試)

1.導入圖像

  1. 獲得一個指向HTMLImageElement或者另一個canvas元素的引用作為源,也可以通過提供一個URL的方式來使用圖片

    圖像源可以是img, video, canvas元素的引用,當然,也可以是當場創建的new Image(),但要注意應該在新的Image對象的load事件處理器中引用它,否則因為圖像沒有加載完成,某些瀏覽器可能會出錯。當然,此外還可以用Base64編碼圖像源。

  2. 使用drawImage()函數將圖片繪制到畫布上

  • drawImage(image, x, y):簡單明了的好方法

  • drawImage(image, x, y, width, height):支持縮放

  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight):支持裁剪(從大圖里摳出一小部分,詳情參見MDN

2.導出圖像

這個當然要比圖像操作更重要,拿着畫布畫了半天,該怎么把它導出成圖片呢

canvas.toDataURL():返回圖像URL,直接把URL賦值給img的src就可以顯示了,它就像一個普通圖片地址一樣,想怎么用就怎么用。但需要注意

  1. 圖像不能來自其它域,嗯,沒錯,又是跨域安全限制,如果來自其它域,toDataURL()方法會拋出錯誤

  2. 看清楚toDataURL方法是canvas的,而不是上面一直在用的ctx上下文對象的,而且方法名的大小寫也比較特殊

3.圖像操作

canvas最強大的功能莫過於獲取圖像數據了,我們可以獲取畫布上每一點的色值,不用canvas能搞定嗎?不能。所以簡單的圖像處理現在已經可以用js搞定了,而不需要后台函數的參與。

比如,對上文中的截圖做一個簡單的反色:

var canvas = document.getElementById('my_canvas');
if(canvas.getContext){
    var ctx = canvas.getContext('2d');//獲取2d上下文
    //畫圖
    var img = document.images[0];
    ctx.drawImage(img, 0, 0);
    //獲取ImageData
    var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var data = imgData.data;//獲取rgba(ImageData的data屬性是每個像素點的rgba值)
    //反色
    var r, g, b, a;
    for(var i = 0, len = data.length;i < len; i+=4){
        //取色
            r = data[i];
            g = data[i+1];
            b = data[i+2];
            //a = data[i+3];//反色不需要透明度
            //反色
            data[i] = 255 - r;
            data[i+1] = 255 - g;
            data[i+2] = 255 - b;
    }

    imgData.data = data;//寫回圖像數據
    ctx.putImageData(imgData, 0, 0);//顯示結果
}

處理效果還是很棒的,如下圖:

反色結果

需要注意一個小問題,Chrome不允許用drawImage畫本地圖片,所以上面的結果是FF下的,在測試Ajax的時候也遇到了類似問題,FF一般在限制跨域安全時不會限制本地資源,而Chrome會,對於服務器上的同源資源則不存在這樣的差異。

四.Canvas的更多功能

漸變、圖案填充、線條控制、陰影、旋轉、變形、縮放、組合、動畫等等更多內容參見參考資料MDN教程

參考資料

  1. MDN教程:很不錯的一篇教程

  2. 《JavaScript高級程序設計》:不舍得還給圖書館的一本好書


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM