Canvas繪圖API總結

碼頭工人 8年前發布 | 16K 次閱讀 JavaScript開發 JavaScript canvas

一. 繪圖API總覽:

  • strokeStyle
  • fillStyle
  • lineWidth
  • save()
  • restore()
  • beginPath()
  • closePath()
  • stroke()
  • lineTo(x, y)
  • moveTo(x, y)
  • quadraticCurveTo(cpx, cpy, x, y)
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
  • arcTo(x1, y1, x2, y2, radius)
  • arc(x, y, radius, startAngle, endAngle [, anticlockwise])
  • createLinearGradient(x0, y0, x1, y1)
  • createRadialGradient(x0, y0, r0, x1, y1, r1)
  • clearRect(x, y, width, height)
  • fillReact(x, y, width, height)

二. canvas上下文

每個canvas元素都包含一個繪圖上下文,可以通過它訪問繪圖API。

var canvas = document.getElementById("canvas"),
    context = canvas.getContext("2d");

getContext()傳入字符串參數”2d”,用于指定將要使用的平面繪圖API類型。

getContext()傳入字符串參數”3d”,用于指定3D繪圖 API,但是目前兼容性極差。

三. 消除圖案

在大多數動畫中,必須在繪制下一幀圖案前清除canvas,通過這樣來模擬出物體正在運動的效果。

context.clearRect(x, y, width, height)方法會通過將像素的顏色設置為全透明的黑色擦除指定區域內的每一個像素,從而清除指定的矩形區域。

四. 設置線條的外觀

  • strokeStyle:指定線條顏色;
  • lineWidth:線條寬度;
  • lineCap:線條重點的繪制樣式。可選值有:butt(默認,延長線)、round(圓的)、square(平的);
  • lineJoin:兩條線段的接合方式。可選值有:round、bevel、miter(默認);
  • miterLimit:用于控制兩條相交線外側交點與內側交點的距離。

五. 使用填充色創建圖形

  • context.fillStyle:填充樣式。可以填充純色、漸變色、pattern和圖片。
  • context.fill():開始填充。

六. 創建簡便填充色

線性漸變context.createLinearGradient(x0, y0, x1, y1):將沿點(x0, y0)與點(x1, y1)之間的直線填充漸變色。

放射性漸變context.createRadialGradient(x0, y0, r0, x1, y1, r1):從指定的空間的中心開始向各個方向擴散,從而創建一個圓形漸變。

6.1 設置漸變點的顏色

可以使用Gradient.addColorStop(ratio, color)方法為漸變色添加漸變點顏色。其中ratio是填充比例,取值范圍為[0, 1]。

例如:

var gradient = context.createLinearGradient(0, 0, 100, 100);
gradient.addColorStop(0, "#fff");
gradient.addColorStop(1, "#000");

七. 繪制的樣式狀態切換

context.save()context.restore()方法可以實現在不同的樣式間切換。

context.save()方法將canvas的當前狀態存入棧中,其中包含各種樣式,例如,strokeStyle、fillStyle以及應用于canvas的變換效果。

context.restore()方法可以使得當前的canvas狀態出棧,轉而使用下一個狀態,即使用之前的狀態。

八. 繪制直線

  • context.beginPath():開始繪制新路徑;
  • context.moveTo(x0, y0):移動到線條起點;
  • context.lineTo(x1, y1):連線到線條終點;
  • context.stroke():繪制線條。

基于上面的繪圖指令,可以創建一個簡單的繪圖程序,如下:

<canvas id="canvas" width="400" height="400" style="background: #ccc;"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d");

function onMouseMove(e) {
    var movePosition = {
        x: getMouse(e).x,
        y: getMouse(e).y
    };
    context.lineTo(movePosition.x, movePosition.y);
    context.stroke();
}

canvas.addEventListener("mousedown", function(e) {
    var curPosition = {
        x: getMouse(e).x,
        y: getMouse(e).y
    };
    context.beginPath();
    context.moveTo(curPosition.x, curPosition.y);
    console.log("curPosition: " + curPosition.x + "; " + curPosition.y);
    canvas.addEventListener("mousemove", onMouseMove, false);
}, false);

canvas.addEventListener("mouseup", function(e) {
    canvas.removeEventListener("mousemove", onMouseMove, false);
}, false);

// 獲取鼠標的當前位置
function getMouse(event) {
    var event = event || window.event;
    var mouse = {};
    var x, y;
    if(event.pageX || event.pageY) {
        x = event.pageX;
        y = event.pageY;
    } else if(event.clientX || event.clientY) {
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        x = event.clientX + scrollLeft;
        y = event.clientY + scrollTop;
    }
    mouse.x = x;
    mouse.y = y;
    return mouse;
}

</script> </code></pre>

演示如下:http://codepen.io/dengzhirong/pen/PzgaRk

See the Pen <a >PzgaRk</a> by dengzhirong (<a >@dengzhirong</a>) on <a >CodePen</a>.

九. 使用quadraticCurveTo繪制曲線

二次貝塞爾曲線quadraticCurveTo(cpx, cpy, x, y)接收兩個點作為參數:第一個點是控制點,用于影響曲線的形狀,第二個點是曲線的終點。

quadraticCurveTo()的繪制方法與lineTo()類似,都是以上一次方法調用的重點或上一個context.moveTo()的位置作為起點。兩者唯一的區別在于繪制出來線條的形狀。

例子:

<canvas id="canvas" width="400" height="400" style="background: #ccc;"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d");

var x0 = 100,
    y0 = 200,
    x2 = 300,
    y2 = 200;

canvas.addEventListener("mousemove", function(e) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    var x1 = getMouse(e).x;
        y1 = getMouse(e).y;
    context.beginPath();
    context.moveTo(x0, y0);
    context.quadraticCurveTo(x1, y1, x2, y2);
    context.stroke();
}, false);

// 獲取鼠標的當前位置
function getMouse(event) {
    var event = event || window.event;
    var mouse = {};
    var x, y;
    if(event.pageX || event.pageY) {
        x = event.pageX;
        y = event.pageY;
    } else if(event.clientX || event.clientY) {
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        x = event.clientX + scrollLeft;
        y = event.clientY + scrollTop;
    }
    mouse.x = x;
    mouse.y = y;
    return mouse;
}

</script> </code></pre>

演示如下:http://codepen.io/dengzhirong/pen/yJAEEP

See the Pen <a >yJAEEP</a> by dengzhirong (<a >@dengzhirong</a>) on <a >CodePen</a>.

9.1 鼠標穿過控制點

如果希望鼠標能穿過控制點,可以用下面的共識計算控制點:(假設:以(x0, y0)作為起點,(x2, y2)作為終點,(x1, y1)作為控制點,(xt, yt)為鼠標所在的點):

x1 = xt * 2 - (x0 + x2) / 2;
y1 = yt * 2 - (y0 + y2) / 2;

可以把上面的程序稍作修改后,使鼠標穿過控制點:

把以下代碼:

var x1 = getMouse(e).x;
    y1 = getMouse(e).y;

改為:

var x1 = getMouse(e).x * 2 - (x0 + x2) / 2;
    y1 = getMouse(e).y * 2 - (y0 + y2) / 2;

演示如下:http://codepen.io/dengzhirong/pen/QEPxBg

See the Pen <a >QEPxBg</a> by dengzhirong (<a >@dengzhirong</a>) on <a >CodePen</a>.

十. 其他形式的曲線繪制

  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y):增加一個到當前路徑的點,并由三次貝塞爾曲線連接兩個控制點;
  • arcTo(x1, y1, x2, y2, radius):使用兩個控制點和指定半徑為連接到前一個點的直線路徑添加一個弧度;
  • arc(x, y, radius, startAngle, endAngle [, anticlockwise]):為連接到前一個點的直線路徑添加一個弧度,該弧度將以x、y作為圓心,以radius為半徑的一個圓的一部分。該弧度的起始角度和終止角度分別由startAngle和endAngle指定。

這些曲線的繪制方法大抵類似。以繪制圓為例子:

context.beginPath();
context.arc(100, 100, 50, 0, (Math.PI * 2), true);
context.closePath();
context.stroke();

十一. 加載并繪制圖片

如果希望在動畫中繪制一張外部圖片,有兩種方式可以用于在動畫中訪問外部圖片:

  • 在腳本運行過程中加載一個URL;
  • 使用DOM接口訪問一個內嵌在HTML中的圖片元素。

當圖片加載完成后,再使用繪圖API將其渲染到canvas。

11.1 加載圖片

為了實現在運行時加載一張圖片,可以創建一個Image對象,并將其src屬性設置為圖片文件的url路徑。當圖片加載完成后,它就會執行onload方法所關聯的回調函數。

如下:

<canvas id="canvas" width="180" height="180" style="background: #ccc;"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        image = new Image();

image.src = "http://www.dengzhr.com/wp-content/themes/dengzhr/images/logo.jpg";
image.onload = function() {
    context.drawImage(image, 0, 0);
};

</script> </code></pre>

使用context.drawImage()方法將圖片繪制到canvas元素上,該方法接受一個圖片元素與canvas上的一個x、y坐標。

context.drawImage()方法有以下三種調用方式,分別使用多個參數:

  • drawImage(image, dx, dy):在canvas的(dx, dy)坐標上繪制一張圖片。(dx, dy)是圖片左上角的位置。
  • drawImage(image, dx, dy, dw, dh):分別根據dw、dh的值設定圖片的寬度與高度,并將其繪制在canvas的(dx, dy)坐標。
  • drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh):將圖片裁剪到矩形區域(sx, sy, dw, dh)中,并縮放至(dw, dh),再將其繪制到(dy, dy)坐標上。

11.2 使用圖片元素

<canvas id="canvas" width="180" height="180" style="background: #ccc;"></canvas>
<img id="img" src=";
<script type="text/javascript">
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        image = document.getElementById("img");

image.onload = function() {
    context.drawImage(image, 0, 0);
};

</script> </code></pre>

11.3 使用視頻元素

除了可以將一幅靜止的圖片繪制到canvas以外,canvas還支持逐幀的視頻渲染。

由于視頻本質上就是按順序播放的一系列靜止的圖像,因此canvas元素會在一個動畫循環中不斷繪制視頻中的當前幀。

如下:

<canvas id="canvas" width="300" height="300" style="background: #ccc;"></canvas>
<video id="video" style="display: none; width: 300px; height: 300px;" autoplay>
    <source src="video.mp4" type="video/mp4" />
    <source src="video.webm" type="video/webm" />
    <source src="video.ogv" type="video/ogg" />
</video>
<script type="text/javascript">
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        video = document.getElementById("video");

    (function drawFrame() {
        window.requestAnimationFrame(drawFrame. canvas);
        context.drawImage(video, 0, 0);
    })();

</script> </code></pre>

來自:http://www.dengzhr.com/js/940

 本文由用戶 碼頭工人 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!