你不知道的Canvas

Posted 墨戈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你不知道的Canvas相关的知识,希望对你有一定的参考价值。

你不知道的Canvas(二)

一、色彩Colors

到目前为止,我们只看到过绘制内容的方法。如果我们想要给图形上色,有两个重要的属性可以做到:fillStylestrokeStyle。

  • fillStyle = color

    设置图形的填充颜色。

  • strokeStyle = color

    设置图形轮廓的颜色。

color 可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象。默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000)。

输入的应该是符合 CSS3 颜色值标准 的有效字符串。下面的例子都表示同一种颜色。

// 这些 fillStyle 的值均为 \'橙色\'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

1.fillStyle--调色板

在本示例里,用两层 for 循环来绘制方格阵列,每个方格不同的颜色。结果如右图,但实现所用的代码却没那么绚丽。我用了两个变量 i 和 j 来为每一个方格产生唯一的 RGB 色彩值,其中仅修改红色和绿色通道的值,而保持蓝色通道的值不变。你可以通过修改这些颜色通道的值来产生各种各样的色板。通过增加渐变的频率,你还可以绘制出类似 Photoshop 里面的那样的调色板。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var ctx = document.getElementById(\'myCanvas\').getContext(\'2d\');
            for (var i = 0; i < 6; i++) {
                for (var j = 0; j < 6; j++) {
                    ctx.fillStyle = \'rgb(\' + Math.floor(255 - 42.5 * i) + \',\'
                        + Math.floor(255 - 42.5 * j) + \',0)\';
                    ctx.fillRect(j * 25, i * 25, 25, 25)
                }
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

2. strokeStyle--arc多彩圆圈

这个示例与上面的有点类似,但这次用到的是 strokeStyle 属性,画的不是方格,而是用 arc 方法来画圆。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById(\'myCanvas\');
            if (canvas.getContext) {
                var ctx = canvas.getContext(\'2d\');
                for (var i = 0; i < 6; i++) {
                    for (var j = 0; j < 6; j++) {
                        ctx.strokeStyle = \'rgb(0,\' + Math.floor(255 - 42.5 * i) + \',\' +
                            Math.floor(255 - 42.5 * j) + \')\';
                        ctx.beginPath();
                        ctx.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, Math.PI * 2, true);
                        ctx.stroke();
                    }
                }
            }
        }
    </script>
</head>

<body onload="draw()">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150" style="margin: 100px 100px;"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

二、透明度Transparency

除了可以绘制实色图形,我们还可以用 canvas 来绘制半透明的图形。通过设置 globalAlpha 属性或者使用一个半透明颜色作为轮廓或填充的样式。

  • globalAlpha = transparencyValue

    这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。

globalAlpha 属性在需要绘制大量拥有相同透明度的图形时候相当高效。不过,我认为下面的方法可操作性更强一点。

因为 strokeStylefillStyle 属性接受符合 CSS 3 规范的颜色值,那我们可以用下面的写法来设置具有透明度的颜色。

// 指定透明颜色,用于描边和填充样式
ctx.strokeStyle = "rgba(255,0,0,0.5)";
ctx.fillStyle = "rgba(255,0,0,0.5)";

rgba() 方法与 rgb() 方法类似,就多了一个用于设置色彩透明度的参数。它的有效范围是从 0.0(完全透明)到 1.0(完全不透明)。

1. globalAlpha--辐射半透明圆四色格

在这个例子里,将用四色格作为背景,设置 globalAlpha0.2 后,在上面画一系列半径递增的半透明圆。最终结果是一个径向渐变效果。圆叠加得越多,原先所画的圆的透明度会越低。通过增加循环次数,画更多的圆,从中心到边缘部分,背景图会呈现逐渐消失的效果。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById(\'myCanvas\');
            if (canvas.getContext) {
                var ctx = canvas.getContext(\'2d\');
                // 画背景
                ctx.fillStyle = \'#FD0\';
                ctx.fillRect(0, 0, 75, 75);
                ctx.fillStyle = \'#6C0\';
                ctx.fillRect(75, 0, 75, 75);
                ctx.fillStyle = \'#09F\';
                ctx.fillRect(0, 75, 75, 75);
                ctx.fillStyle = \'#F30\';
                ctx.fillRect(75, 75, 75, 75);
                ctx.fillStyle = \'#FFF\';

                // 设置透明度值
                ctx.globalAlpha = 0.2;

                // 画半透明圆
                for (var i = 0; i < 7; i++) {
                    ctx.beginPath();
                    ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);
                    ctx.fill();
                }
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

2. rgba--四色辐射矩形格

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById(\'myCanvas\');
            if (canvas.getContext) {
                var ctx = canvas.getContext(\'2d\');
                // 画背景
                ctx.fillStyle = \'rgb(255,221,0)\';
                ctx.fillRect(0, 0, 150, 37.5);
                ctx.fillStyle = \'rgb(102,204,0)\';
                ctx.fillRect(0, 37.5, 150, 37.5);
                ctx.fillStyle = \'rgb(0,153,255)\';
                ctx.fillRect(0, 75, 150, 37.5);
                ctx.fillStyle = \'rgb(255,51,0)\';
                ctx.fillRect(0, 112.5, 150, 37.5);

                // 画半透明矩形
                for (var i = 0; i < 10; i++) {
                    ctx.fillStyle = \'rgba(255,255,255,\' + (i + 1) / 10 + \')\';
                    for (var j = 0; j < 4; j++) {
                        ctx.fillRect(5 + i * 14, 5 + j * 37.5, 14, 27.5)
                    }
                }
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

三、线型Line Style

可以通过一系列属性来设置线的样式。

  • lineWidth = value

    设置线条宽度。

  • lineCap = type

    设置线条末端样式。

  • lineJoin = type

    设定线条与线条间接合处的样式。

  • miterLimit = value

    限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。

  • getLineDash()

    返回一个包含当前虚线样式,长度为非负偶数的数组。

  • setLineDash(segments)

    设置当前虚线样式。

  • lineDashOffset = value

    设置虚线样式的起始偏移量。

通过以下的样例可能会更加容易理解。

1. lineWidth 属性的例子

这个属性设置当前绘线的粗细。属性值必须为正数。默认值是1.0。

线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半。因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。

在下面的例子中,用递增的宽度绘制了10条直线。最左边的线宽1.0单位。并且,最左边的以及所有宽度为奇数的线并不能精确呈现,这就是因为路径的定位问题。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var ctx = document.getElementById(\'myCanvas\').getContext(\'2d\');
            for (var i = 0; i < 10; i++) {
                ctx.beginPath();
                ctx.lineWidth = 1 + i;
                ctx.moveTo(5 + i * 14, 5);
                ctx.lineTo(5 + i * 14, 140);
                ctx.stroke();
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

2. lineCap 属性的例子

img属性 lineCap 的值决定了线段端点显示的样子。它可以为下面的三种的其中之一:buttroundsquare。默认是 butt。

在这个例子里面,我绘制了三条直线,分别赋予不同的 lineCap 值。还有两条辅助线,为了可以看得更清楚它们之间的区别,三条线的起点终点都落在辅助线上。

最左边的线用了默认的 butt 。可以注意到它是与辅助线齐平的。中间的是 round 的效果,端点处加上了半径为一半线宽的半圆。右边的是 square 的效果,端点处加上了等宽且高度为一半线宽的方块。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var ctx = document.getElementById(\'myCanvas\').getContext(\'2d\');

            var lineCap = [\'butt\', \'round\', \'square\'];

            // 创建路径
            ctx.strokeStyle = \'#09f\';
            ctx.beginPath();
            ctx.moveTo(10, 10);
            ctx.lineTo(140, 10);
            ctx.moveTo(10, 140);
            ctx.lineTo(140, 140);
            ctx.stroke();

            // 画线条
            ctx.strokeStyle = \'black\';
            for (var i = 0; i < lineCap.length; i++) {
                ctx.lineWidth = 15;
                ctx.lineCap = lineCap[i];
                ctx.beginPath();
                ctx.moveTo(25 + i * 50, 10);
                ctx.lineTo(25 + i * 50, 140);
                ctx.stroke();
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

3. lineJoin属性的例子

imglineJoin 的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round, bevelmiter。默认是 miter``。

这里我同样用三条折线来做例子,分别设置不同的 lineJoin 值。最上面一条是 round 的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter 的效果。当值是 miter 的时候,线段会在连接处外侧延伸直至交于一点,延伸效果受到下面将要介绍的 miterLimit 属性的制约。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var ctx = document.getElementById(\'myCanvas\').getContext(\'2d\');
            var lineJoin = [\'round\', \'bevel\', \'miter\'];
            ctx.lineWidth = 10;
            for (var i = 0; i < lineJoin.length; i++) {
                ctx.lineJoin = lineJoin[i];
                ctx.beginPath();
                ctx.moveTo(-5, 5 + i * 40);
                ctx.lineTo(35, 45 + i * 40);
                ctx.lineTo(75, 5 + i * 40);
                ctx.lineTo(115, 45 + i * 40);
                ctx.lineTo(155, 5 + i * 40);
                ctx.stroke();
            }
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

4. 使用虚线

setLineDash 方法和 lineDashOffset 属性来制定虚线样式. setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset 属性设置起始偏移量.

在这个例子中,我们要创建一个蚂蚁线的效果。它往往应用在计算机图形程序选区工具动效中。它可以帮助用户通过动画的边界来区分图像背景选区边框。

四、渐变Gradients

就好像一般的绘图软件一样,我们可以用线性或者径向的渐变来填充或描边。我们用下面的方法新建一个 canvasGradient 对象,并且赋给图形的 fillStylestrokeStyle 属性。

  • createLinearGradient(x1, y1, x2, y2)

    createLinearGradient 方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。

  • createRadialGradient(x1, y1, r1, x2, y2, r2)

    createRadialGradient 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。

var lineargradient = ctx.createLinearGradient(0,0,150,150);
var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);

创建出 canvasGradient 对象后,我们就可以用 addColorStop 方法给它上色了。

  • gradient.addColorStop(position, color)

    addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。

你可以根据需要添加任意多个色标(color stops)。下面是最简单的线性黑白渐变的例子。

var lineargradient = ctx.createLinearGradient(0,0,150,150);
lineargradient.addColorStop(0,\'white\');
lineargradient.addColorStop(1,\'black\');

1.createLinearGradient 的例子

img

本例中,有两种不同的渐变。第一种是背景色渐变,你会发现,我给同一位置设置了两种颜色,你也可以用这来实现突变的效果,就像这里从白色到绿色的突变。一般情况下,色标的定义是无所谓顺序的,但是色标位置重复时,顺序就变得非常重要了。所以,保持色标定义顺序和它理想的顺序一致,结果应该没什么大问题。

第二种渐变,我并不是从 0.0 位置开始定义色标,因为那并不是那么严格的。在 0.5 处设一黑色色标,渐变会默认认为从起点到色标之间都是黑色。

你会发现,strokeStylefillStyle 属性都可以接受 canvasGradient 对象。

2. createRadialGradient的例子

这个例子,我定义了 4 个不同的径向渐变。由于可以控制渐变的起始与结束点,所以我们可以实现一些比(如在 Photoshop 中所见的)经典的径向渐变更为复杂的效果。(经典的径向渐变是只有一个中心点,简单地由中心点向外围的圆形扩张)

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById(\'myCanvas\');
            var ctx = canvas.getContext(\'2d\');
            // 创建渐变
            var radgrad = ctx.createRadialGradient(45, 45, 10, 52, 50, 30);
            radgrad.addColorStop(0, \'#A7D30C\');
            radgrad.addColorStop(0.9, \'#019F62\');
            radgrad.addColorStop(1, \'rgba(1,159,98,0)\');

            var radgrad2 = ctx.createRadialGradient(105, 105, 20, 112, 120, 50);
            radgrad2.addColorStop(0, \'#FF5F98\');
            radgrad2.addColorStop(0.75, \'#FF0188\');
            radgrad2.addColorStop(1, \'rgba(255,1,136,0)\');

            var radgrad3 = ctx.createRadialGradient(95, 15, 15, 102, 20, 40);
            radgrad3.addColorStop(0, \'#00C9FF\');
            radgrad3.addColorStop(0.8, \'#00B5E2\');
            radgrad3.addColorStop(1, \'rgba(0,201,255,0)\');

            var radgrad4 = ctx.createRadialGradient(0, 150, 50, 0, 140, 90);
            radgrad4.addColorStop(0, \'#F4F201\');
            radgrad4.addColorStop(0.8, \'#E4C700\');
            radgrad4.addColorStop(1, \'rgba(228,199,0,0)\');

            // 画图形
            ctx.fillStyle = radgrad4;
            ctx.fillRect(0, 0, 150, 150);
            ctx.fillStyle = radgrad3;
            ctx.fillRect(0, 0, 150, 150);
            ctx.fillStyle = radgrad2;
            ctx.fillRect(0, 0, 150, 150);
            ctx.fillStyle = radgrad;
            ctx.fillRect(0, 0, 150, 150);
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

这里,我让起点稍微偏离终点,这样可以达到一种球状 3D 效果。但最好不要让里圆与外圆部分交叠,那样会产生什么效果就真是不得而知了。

4 个径向渐变效果的最后一个色标都是透明色。如果想要两色标直接的过渡柔和一些,只要两个颜色值一致就可以了。代码里面看不出来,是因为我用了两种不同的颜色表示方法,但其实是相同的,#019F62 = rgba(1,159,98,1)。

五、图案样式Patterns

上面的一个例子里面,我用了循环来实现图案的效果。其实,有一个更加简单的方法:createPattern。

  • createPattern(image, type)

    该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeatrepeat-xrepeat-yno-repeat

注意: 用 canvas 对象作为 Image 参数在 Firefox 1.5 (Gecko 1.8) 中是无效的。

图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给 fillStylestrokeStyle 属性即可。

var img = new Image();
img.src = \'someimage.png\';
var ptrn = ctx.createPattern(img,\'repeat\');

注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。

1. createPattern的例子

在最后的例子中,我创建一个图案然后赋给了 fillStyle 属性。唯一要注意的是,使用 Image 对象的 onload handler 来确保设置图案之前图像已经装载完毕。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <script type="text/javascript">
            function draw() {
                var canvas = document.getElementById(\'myCanvas\');
                var ctx = canvas.getContext(\'2d\');

                //创建新Image对象,用做图案
                var img = new Image();
                img.src = \'https://pic.cnblogs.com/avatar/1489272/20190625145401.png\';
                img.onload = function() {

                    //创建图案
                    var pattern = ctx.createPattern(img, "repeat");
                    ctx.fillStyle = pattern;
                    ctx.fillRect(0, 0, 150, 150);
                }
            }
        </script>
    </head>
    <body onload="draw();">
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <canvas id="myCanvas" width="150" height="150">

        </canvas>
        <script src="" async defer></script>
    </body>
</html>

效果如图所示:

六、阴影Shadows

shadowOffsetX = float

shadowOffsetXshadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0

shadowOffsetY = float

shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0

shadowBlur = float

shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0

shadowColor = color

shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。

1. 文字阴影的例子

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <script type="text/javascript">
            function draw() {
                var canvas = document.getElementById(\'myCanvas\');
                var ctx = canvas.getContext(\'2d\');

                ctx.shadowOffsetX = 2;
                ctx.shadowOffestY = 2;
                ctx.shadowBlur = 2;
                ctx.shadowColor = \'rgba(0, 0, 0, 0.5)\';

                ctx.font = \'20px Times New Roman\';
                ctx.fillStyle = \'red\';
                ctx.fillText("Hello, World!", 5, 30);
            }
        </script>
    </head>
    <body onload="draw();">
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <canvas id="myCanvas" width="150" height="150"></canvas>
        <script src="" async defer></script>
    </body>
</html>

效果如图所示:

七、Canvas填充规则

当我们用到 fill(或者 clipisPointinPath)你可以选择一个填充规则,该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。

两个可能的值:

  • **"nonzero**": non-zero winding rule, 默认值.
  • **"evenodd"**: even-odd winding rule.

这个例子,我们用填充规则 evenodd

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById(\'myCanvas\');
            var ctx = canvas.getContext(\'2d\');
            ctx.beginPath();
            ctx.arc(50, 50, 30, 0, Math.PI * 2, true);
            ctx.arc(50, 50, 15, 0, Math.PI * 2, true);
            ctx.fill("evenodd");
        }
    </script>
</head>

<body onload="draw();">
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <canvas id="myCanvas" width="150" height="150"></canvas>
    <script src="" async defer></script>
</body>

</html>

效果如图所示:

以上是关于你不知道的Canvas的主要内容,如果未能解决你的问题,请参考以下文章

Go 语言 10 岁了!这里有你不知道的 Go 的成长历程

Go 语言也 10 岁了!这里或许有你不知道的 Go 的成长历程

30分钟学完canvas动画|游戏基础(extra1):颜色那些事

小程序各种功能代码片段整理---持续更新

你不知道的代码评价

你不知道的 VSCode 代码高亮原理