Skip to content

三、样式和颜色

1.色彩 Colors

如果我们想要给图形上色,有两个重要的属性可以做到:fillStylestrokeStyle

  • 设置图形的填充颜色:fillStyle = color
  • 设置图形轮廓的颜色:strokeStyle = color
  • color 可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象
js
// 这些 fillStyle 的值均为 '橙色'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

2.透明度 Transparency

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

可以通过两种方式设置透明度

2.1 globalAlpha

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

js
ctx.globalAlpha = 0.2

2.2 rgba()

通过fillStylestrokeStyle 设置透明的填充颜色或边框颜色

js
ctx.fillStyle = "rgba(0,0,0,0.2)";

3.线型 Line styles

可以下列属性来设置线的样式。

3.1 lineWidth

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

js
ctx.lineWidth = 1;

3.2 lineCap

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

  • butt:默认值,末端为矩形
  • round :末端为圆形
  • square:末端为突出的矩形,矩形宽度不变,高度为线条宽度的一半
js
ctx.lineCap='butt'|'round'|'square'

效果如下图

img

3.3 lineJoin

lineJoin 的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:

  • round:交点为扇形
  • bevel:交点为三角形底边
  • miter:默认值,交点为菱形。
js
ctx.lineJoin ='round'|'bevel'|'miter'

下图从上到下分别是值为round,bevel,miter的效果

image-20230528165739305

3.4 miterLimit

指定交点菱形的长度,默认为10。该属性只在lineJoin属性的值等于miter时有效

image-20230528165846464

3.5 setLineDash

setLineDash() 方法接受一个数组

这个函数里面的参数依次是:实线 空白 实线 空白的宽度,依次循环

js
ctx.setLineDash([30,30,5,5,....])

image-20230528171935895

3.6 getLineDash

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

js
const canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var offset = 0;

ctx.lineWidth = 20;
ctx.beginPath();
ctx.moveTo(5, 5);
ctx.lineTo(500, 5);
// 设置虚线样式
ctx.setLineDash([30, 30, 5, 5]);
ctx.stroke();

console.log(ctx.getLineDash()); // [30, 30, 5, 5]

3.7 lineDashOffset

设置虚线偏移量的属性

value是 float 精度的数字。初始值为 0.0

js
ctx.lineDashOffset = value;

蚂蚁线

蚂蚁线效果是一种动画技巧,经常出现在计算机绘图程序的套索工具中。它能帮助用户根据图片背景动态变化的边界来区分选择的边界。

js
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var offset = 0;

function draw() {
    ctx.clearRect(0,0, canvas.width, canvas.height);
    ctx.setLineDash([4, 2]);
    ctx.lineDashOffset = -offset;
    ctx.strokeRect(10,10, 100, 100);
}

function march() {
    offset++;
    if (offset > 16) {
        offset = 0;
    }
    draw();
    setTimeout(march, 20);
}

march();

mayi

4.渐变 Gradients

设置渐变主要有以下四步

  1. 使用createLinearGradientcreateRadialGradient创建渐变位置
  2. 使用addColorStop给渐变上色
  3. 把渐变对象赋值给fillStyle或者StrokeStyle完成渐变
  4. 绘制图形

4.1 createLinearGradient()

作用:返回一个线性渐变对象,用于设置线性渐变

语法

js
createLinearGradient(x1, y1, x2, y2)

参数

  • x1, y1:渐变的起点坐标
  • x2, y2:渐变的终点坐标

image-20230713121326181

示例

js
var lineargradient = ctx.createLinearGradient(0,0,150,150);

4.2 createRadialGradient()

作用:返回一个径向渐变对象,用于设置径向渐变,参数为两个圆,分别称之为圆1和圆2

  • 圆1所在的弧线即是渐变的起始位置
  • 圆2所在的弧线即是渐变的终点位置

语法:

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

参数:

  • x1, y1:圆1的圆心坐标
  • r1:圆1的半径
  • x2, y2:圆2的圆心坐标
  • r2:圆2的半径

示例:

js
var gradient = ctx.createRadialGradient(100, 100, 50, 100, 100, 100);

4.3 createConicGradient()

作用:返回一个锥形渐变对象,用于设置锥形渐变

语法:

js
createConicGradient(startAngle, x, y)

参数:

  • startAngle:开始渐变的角度(以弧度为单位)。角度从从中心水平方向的直线开始,顺时针方向前进。
  • x:渐变中心的 x 轴坐标。
  • y:渐变中心的 y 轴坐标。

示例

js
const gradient = ctx.createConicGradient(0, 100, 100);

4.3 addColorStop()

作用:给渐变上色

语法

js
gradient.addColorStop(position, color)

参数

  • position表示渐变中颜色所在的相对位置,取值范围在0.0 - 1.0
    • 0表示起点,1表示终点,0.5表示中间点
  • color 参数必须是一个有效的 CSS 颜色值(可以是十六进制颜色值,rgba,或者是颜色关键词)。

注意最后要把渐变对象赋值给fillStyle或者StrokeStyle属性

设置线性渐变

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

ctx.fillStyle = lineargradient;
ctx.fillRect(0, 0, 150, 150);

image-20230713120030715

设置径向渐变

js
var gradient = ctx.createRadialGradient(100, 100, 50, 100, 100, 100);
gradient.addColorStop(0, "blue");
gradient.addColorStop(1, "red");
ctx.beginPath();
ctx.fillStyle = gradient;
ctx.arc(100, 100, 100, 0, Math.PI * 2);
ctx.fill()
ctx.closePath();

image-20230713120052086

设置锥形渐变

js
const gradient = ctx.createConicGradient(0, 100, 100);

gradient.addColorStop(0, "red");
gradient.addColorStop(0.25, "orange");
gradient.addColorStop(0.5, "yellow");
gradient.addColorStop(0.75, "green");
gradient.addColorStop(1, "blue");

ctx.fillStyle = gradient;
ctx.arc(100, 100, 100, 0, Math.PI * 2);
ctx.fill();

image-20230713120823856

5.图案样式 Patterns

5.1 createPattern()

createPattern()方法定义一个图像填充样式,在指定方向上不断重复该图像,填充指定的区域。

该方法接受两个参数

  • 第一个参数是图像数据,它可以是<img>元素,也可以是另一个<canvas>元素,或者一个表示图像的 Blob 对象
  • 第二个参数是一个字符串,有四个可能的值,分别是:
    • repeat:双向重复
    • repeat-x:水平重复
    • repeat-y:垂直重复
    • no-repeat:不重复

如果第二个参数是空字符串或null,则等同于null

该方法的返回值是一个CanvasPattern对象,需要将返回值赋值给fillStyle属性

注意:使用 Image 对象的 onload() 方法来确保设置图案之前图像已经装载完毕。

js
function draw() {
    var ctx = document.querySelector("canvas").getContext("2d");

    // 创建新 image 对象,用作图案
    var img = new Image();
    img.src ="http://www.zuohaotu.com/images/%E5%81%9A%E5%A5%BD%E5%9B%BE.png";
    img.onload = function () {
        // 创建图案
        var ptrn = ctx.createPattern(img, "repeat");
        ctx.fillStyle = ptrn;
        ctx.fillReact(0, 0, 150, 150);
    };
}

6.阴影 Shadows

通过设置绘制上下文的以下属性,可给图形添加阴影

  • shadowOffsetX:阴影的水平位移,默认为0
  • shadowOffsetY:阴影的垂直位移,默认为0
  • shadowBlur:阴影的模糊程度,默认为0
  • shadowColor:阴影的颜色,默认为black
    • 可以是颜色名,十六进制颜色值,rgba
js
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 5;
ctx.shadowColor = 'rgba(0,0,0,0.5)';

ctx.fillStyle = 'green';
ctx.fillRect(10, 10, 100, 100);

image-20230528183734043

7.填充规则

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

如果只是几个点圈起来的一个区域那么这两种规则没有区别

但是当发生线的焦点时就会呈现差异

两个值:

  • "nonzero": non-zero winding rule, 默认值.

onzero规则”顾名思意就是“非零规则”,用通俗的话讲,就算计算某些东西是不是0,如果不是0则内部,填充;如果是0则外部,不填充。

  • "evenodd": even-odd winding rule

    “evenodd规则”顾名思意就是“奇偶规则”,用通俗的话讲,就算计算某些东西是不是奇数,如果是是奇数则内部,填充;如果是偶数则外部,不填充。

nonzero规则和evenodd规则计算的东西还不一样,nonzero是计算顺时针逆时针数量,evenodd是交叉路径数量。

怎么判断

在这个区域内任意找一个点,然后以这个点为起点,发射一条无限长的射线

  • 对于nonzero规则:起始值为0,射线会和路径相交,如果路径方向和射线方向形成的是顺时针方向则+1,如果是逆时针方向则-1,最后如果数值为0,则是路径的外部;如果不是0,则是路径的内部,因此被称为“非0规则”。
  • 对于evenodd规则:起始值为0,射线会和路径相交,每交叉一条路径,我们计数就+1,最后看我们的总计算数值,如果是奇数,则认为是路径内部,如果是偶数,则认为是路径外部。
js
function draw() {
    var ctx = document.getElementById("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.arc(50, 50, 10, 0, Math.PI * 2, true);
    ctx.fill("evenodd");
}

image-20230528185132998

MIT Licensed