高级功能使用canvas元素(第二部分)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级功能使用canvas元素(第二部分)相关的知识,希望对你有一定的参考价值。

 本文将继续介绍canvas的功能,展示如何绘制更复杂的图形(包括圆弧和曲线),如何使用剪裁区域来限制操作以及如何绘制文本。还是介绍可以应用在画布上的特效和变换,包括阴影、透明度、旋转和坐标重映射。

1. 用路径绘图

路径本质上是一组独立的线条(被称为子路径),它们组合到一起构成图形。我们绘制子路径的方式就像用笔在纸上画图一样,笔尖不离开纸面:画布上的每一条子路径都以上一条的终点作为起点。下面展示了绘制基本路径的方法:

绘制一条路径的基本顺序如下:

* 调用 beginPath方法;

* 用 moveTo方法移动到起点;

* 用 arc和 lineTo等方法绘制子路径;

* 调用 closePath方法(可选)

* 调用 fill或 stroke方法

 

1.1 用线条绘制路径

最简单的路径是那些由直线所组成的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>由直线创建路径</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn\'t support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 4;

    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.lineTo(110,10);
    ctx.lineTo(110,120);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(150,10);
    ctx.lineTo(200,10);
    ctx.lineTo(200,120);
    ctx.lineTo(190,120);
    ctx.fill();
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(250,10);
    ctx.lineTo(250,120);
    ctx.stroke();
</script>
</body>
</html>

此例创建了三条路径,其显示效果如下:

对于第一条路径。此例明确绘制了两条线,然后使用closePath方法,这样canvas就会闭合路径。然后调用了fill方法,用fillStyle属性所定义的样式填充了这个图形。

对于第二个图形,此例指定了三条子路径,然没有闭合图形。可以看到调用了fill和stroke这两个方法来给图形填色,并沿着路径绘制了一条线。请注意填充色的绘制方式就行图形已经闭合了那样。canvas元素会假定存在一条从终点到起点的子路径,然后借助它填充图形。相比之下,stroke方法只会沿着已经定义的子路径。

PS:对于第二个图形,在stroke方法之前先调用了fill方法,这会使canvas先用纯色填充图形,然后再沿着路径绘制线条。如果lineWidth属性大于1并且先调用了stroke方法,得到的视觉效果就会有所不同。更宽的线条会在路径两侧绘制。因此线条的一部分会在调用fill方法时被遮盖,导致线条的宽度变窄。

对于第三个图形,此例只是简单地在两点之间绘制了一条线,因为路径不一定需要包含多条子路径。我们在绘制线条或未闭合图形时可以使用 lineCap属性来设置线条末端的样式。这个属性允许的三个值是:butt、round 和square(butt为默认值)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置lineCap属性</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn\'t support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.strokeStyle = "red";
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(0,50);
    ctx.lineTo(200,50);
    ctx.stroke();

    ctx.strokeStyle = "black";
    ctx.lineWidth = 40;

    var xpos = 50;
    var styles = ["butt","round","square"];
    for(var i=0;i<styles.length;i++){
        ctx.beginPath();
        ctx.lineCap = styles[i];
        ctx.moveTo(xpos,50);
        ctx.lineTo(xpos,150);
        ctx.stroke();
        xpos += 50;
    }
</script>
</body>
</html>

此例的脚本为每一种样式都绘制了一条非常粗的线。默认值作为参考线,用它演示 round和 square样式在绘制时会超过线条末端。

 

1.2 绘制矩形

rect 方法会给当前路径添加一条矩形的子路径。如果只需要一个单独的矩阵,那么之前介绍的 fillRect和 strokeRect方法是更合适的选择。如果需要给一个更复杂的图像添加矩形,rect方法就很有用了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用rect方法绘制矩形</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn\'t support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
ctx.fillStyle
= "yellow"; ctx.strokeStyle = "red"; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(110,10); ctx.lineTo(110,100); ctx.lineTo(10,10); ctx.closePath(); ctx.rect(110,10,100,90); ctx.rect(110,100,130,30); ctx.fill(); ctx.stroke(); </script> </body> </html>

使用rect方法时不需要moveTo方法,因为我们在此方法的前两个参数里已经指定了矩形的坐标。此例绘制了一对线条,调用closePath方法创建了一个三角形,然后绘制了两个邻接的矩形,此例显示效果如下:

子路径不一定需要相连才能组成路径。可以绘制几条分离的子路径,它们仍然会被视为同一个图形的组成部分。修改JavaScript代码如下:

<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "red";
    ctx.lineWidth = 4;

    ctx.beginPath();
    ctx.moveTo(110,10);
    ctx.lineTo(110,100);
    ctx.lineTo(10,10);
    ctx.closePath();

    ctx.rect(120,10,100,90);
    ctx.rect(150,110,130,20);

    ctx.fill();
    ctx.stroke();
</script>

此例里的子路径之间并不相连,但总体结果仍然是一条单独的路径。当调用 stroke或 fill方法时,它们的效果会应用到所有创建的子路径上,其显示效果如下:

 

2. 绘制圆弧

我们使用 arc和 arcTo方法在画布上绘制圆弧,不过这两种方法绘制圆弧的方式有所不同。下表介绍了canvas里与圆弧有关的方法:

 

 

2.1 使用arcTo方法

下例演示了如何使用arcTo方法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用arcTo方法</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn\'t support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    var point1 = [100,10];
    var point2 = [200,10];
    var point3 = [200,110];
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "blue";
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.moveTo(point1[0],point1[1]);
    ctx.arcTo(point2[0],point2[1],point3[0],point3[1],100);
    ctx.stroke();

    drawPoint(point1[0],point1[1]);
    drawPoint(point2[0],point2[1]);
    drawPoint(point3[0],point3[1]);

    ctx.beginPath();
    ctx.moveTo(point1[0],point1[1]);
    ctx.lineTo(point2[0],point2[1]);
    ctx.lineTo(point3[0],point3[1]);
    ctx.stroke();

    function drawPoint(x,y){
        ctx.lineWidth = 1;
        ctx.strokeStyle = "red";
        ctx.strokeRect(x-2,y-2,4,4);
    }
</script>
</body>
</html>

arcTo方法绘制的圆弧依靠两条线完成。第一条是从上一条子路径的终点绘制到前两个方法参数所描述的点。第二条线是从前两个方法参数所描述的点绘制到第三个和第四个参数所描述的点。然后canvas会绘制从上一条子路径的终点到第二个点之间最短的一条圆弧,其半径由最后一个参数指定。为了让它便于理解,此例给画布添加了两条额外的路径来提供一些上下文信息,此例显示效果如下:

可以看到两条红色的线。此例指定了一个半径,两条线的长度也完全一致,这就意味着我们得到一条匀称的曲线,刚好触碰到上一条子路径的终点和第三个与第四个参数所描述的点。半径和线条长度并不总是具有如此方便的尺寸,所以canvas会根据需要调整所绘制的圆弧。演示例子如下,此例使用事件监控鼠标运动,在屏幕上的鼠标移动时为不同的点绘制圆弧:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>响应鼠标绘制移动绘制圆弧</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn\'t support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var canvasElement = document.getElementById("canvas");
    var ctx = document.getElementById("canvas").getContext("2d");
    var point1 = [100,10];
    var point2 = [200,10];
    var point3 = [200,110];
    draw();

    canvasElement.onmousemove = function(e){
        if(e.ctrlKey){
            point1 = [e.clientX, e.clientY];
        }else if(e.shiftKey){
            point2 = [e.clientX, e.clientY];
        }else {
            point3 = [e.clientX, e.clientY];
        }
        ctx.clearRect(0,0,500,140);
        draw();
    }

    function draw(){
        ctx.

以上是关于高级功能使用canvas元素(第二部分)的主要内容,如果未能解决你的问题,请参考以下文章

Natasha 高级编译类 - 第二部分

Mecanim 动画系统(第二部分)

自学总结redis第二部分(redis常用命令高级命令特性以及与java代码的结合)

python类的相关知识第二部分

python学习-第二部分

JavaScript笔试题(js高级代码片段)