canvas 爬坑路【方法篇】

2,367 阅读11分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

canvas 相关方法及其用法

arc()

绘制圆弧和圆圈。

/**
x: 圆弧中心的 x 轴坐标
y: 圆弧中心的 y 轴坐标
radius: 圆弧的半径
startAngle: 圆弧的起始点,x 轴方向开始计算,单位弧度
endAngle: 圆弧的终点
anticlockwise: Bool 值可选, true: 逆时针绘制圆弧 false: 顺时针绘制,默认为false
*/
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

示例:

ctx.beginPath();
ctx.arc(75, 75, 50, 0, 10);
ctx.stroke();
// 页面就会出现一个半径为50的⚪

效果: image.png

arcTo()

根据控制点和半径绘制一个圆弧路径。使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。

/**
x1: 第一个控制点的 x 轴坐标
y1: 第一个控制点的 y 轴坐标
x2: 第二个控制点的 x 轴坐标
y2: 第二个控制点的 y 轴坐标
radius: 圆弧的半径
*/
ctx.arcTo(x1, y1, x2, y2, radius)

示例:

ctx.beginPath();
ctx.moveTo(50, 50);
ctx.arcTo(65, 150, 202, 57, 40);
// 注意一般lineTo 这里的数据要和 arcTo 第二个控制点坐标保持一致
ctx.lineTo(202, 57);
ctx.stroke();

效果:

image.png

beginPath()

表示要开始绘制一个新的路径了,和之前绘制的没有任何关系了。这个 api 有心的同学已经发现上边好多示例都用过了。

bezierCurveTo()

用来绘制 贝塞尔曲线 需要三个控制点,前两个市控制点,第三个是结束点。起点可以是当前路径的最后一个点。

/**
cp1x: 第一个控制点的 x 轴坐标。
cp1y: 第一个控制点的 y 轴坐标。
cp2x: 第二个控制点的 x 轴坐标。
cp2y: 第二个控制点的 y 轴坐标。
x: 结束点的 x 轴坐标。
y: 结束点的 y 轴坐标。
*/
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

示例:

context.beginPath();
context.moveTo(50, 50);
context.bezierCurveTo(95, 150, 226, 0, 250, 100);
context.stroke();

效果:

image.png

clearRect()

可以把画布中的某一块矩形区域设置为透明色

/**
x:矩形左上角 x 坐标
y:矩形左上角 y 坐标
width:矩形区域宽度
height:矩形区域高度
*/
ctx.clearRect(x, y, width, height)

示例:

ctx.fillStyle = '#000'
ctx.fillRect(10,10,150,150)
ctx.clearRect(20,20,80,80)

效果:

image.png

clip()

路径剪裁,先绘制剪裁路径,再绘制其他内容就在这个剪裁路径中呈现了。

/**
path: Object 指path2D对象 可选
fillRule: 用来确定一个点是在路径内还是路径外。可选值:
    - nonzero 非零环绕原则,默认值
    - evenodd 奇偶环绕原则。
*/
ctx.clip(path, fillRule)

示例:

 // 绘制一个圆然后剪裁,再绘制一个正方形或者绘制一个图片
ctx.arc(100,100,50,0,20)
ctx.clip()
ctx.fillRect(0,0,200,200)
ctx.drawImage(img,0,0,300,300)

效果:

image.png

closePath()

闭合路径会讲路径的开始位置和结束位置相连接,如果只有一个点则不生效。

ctx.closePath()

示例:

ctx.beginPath()
ctx.moveTo(80, 80)
ctx.lineTo(100, 50)
ctx.lineTo(170, 90)
ctx.closePath()
ctx.stroke();

效果:

image.png

createImageData()

创建一个新的、空白的 ImageData 对象。

/**
width: ImageData 对象的 width 值
height: ImageData 对象的 height 值
imagedata: 复制一个和其宽度和高度相同的对象。图像自身不允许被复制。
*/
ctx.createImageData(width, height); 
ctx.createImageData(imagedata);
// 可以在控制台打印一下看看。

createLinearGradient()

创建线性渐变对象

/**
x0: 渐变起始点横坐标
y0: 渐变起始点纵坐标
x1: 渐变结束点横坐标
y1: 渐变结束点纵坐标
*/
ctx.createLinearGradient(x0, y0, x1, y1)

示例:

// 绘制一个由灰渐变到黑的矩形
var gradient = ctx.createLinearGradient( 0, 0, 300, 0)
gradient.addColorStop(0, '#CCC')
gradient.addColorStop(1, '#000')
ctx.fillStyle = gradient
ctx.fillRect(50, 50, 200, 100)

效果:

image.png

createPattern()

创建图案对象。返回值是CanvasPattern对象。

/**
image:
    作为重复图像源的 CanvasImageSource 对象。可以是下列之一:
    HTMLImageElement (<img>),
    HTMLVideoElement (<video>),
    HTMLCanvasElement (<canvas>),
    CanvasRenderingContext2D,
    ImageBitmap,
    ImageData,
    Blob.
repetition
指定如何重复图像。允许的值有:
"repeat" (水平和垂直平铺。当repetition属性值为空字符串''或者null,也会按照'repeat'进行渲染),
"repeat-x" (水平平铺),
"repeat-y" (垂直平铺), 
"no-repeat" (不平铺).
*/
ctx.createPattren(image, repetition)

示例:

var img = new Image(); 
img.src='./xx.png'
img.onload =function() {
    ctx.fillStyle = ctx.createPattern(img, null)  
    ctx.fillRect(0, 0, 400, 400)
}

效果:

image.png

createRadialGradient()

确定两个圆的坐标,绘制放射性渐变的方法。

/**
x0: 开始圆的 x 轴坐标。
y0 开始圆的 y 轴坐标。
r0: 开始圆的半径。
x1: 开始圆的 x 轴坐标。
y1: 开始圆的 y 轴坐标。
r1: 结束圆的半径
*/
createRadialGradient(x0, y0, r0, x1, y1, r1)

示例:

let gradient = ctx.createRadialGradient(100, 100, 100, 100, 100, 0)
gradient.addColorStop(0, "#CCC")
gradient.addColorStop(1, "#000")
ctx.fillStyle = gradient
ctx.fillRect(0,0,200,200)

效果:

image.png

drawFocusIfNeeded()

可以让当前路径或者指定路径轮廓高亮,如果指定元素处于focus状态。

/**
element: 是否需要设置焦点元素
path: 路径
*/
ctx.drawFocusIfNeeded(element);
ctx.drawFocusIfNeeded(path, element);

示例:

<canvas id='canvas' width="300" height="300">
    <button id="btn">btn</button>
</canvas>
// 获取 btn
const btn = document.getElementById('btn')
const canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
btn.focus()
ctx.beginPath()
ctx.rect(100,100,100,50)
ctx.drawFocusIfNeeded(btn)

效果:

image.png

drawImage()

在 Canvas 上绘制图像。

/**
img: 绘制到上下文的元素。
sx: 可选 需要绘制到目标上下文,img 左上角 x 轴坐标。
sy: 可选 需要绘制到目标上下文,img 左上角 Y 轴坐标。
sWidth: 可选 需要绘制到目标上下文中的,img的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的sx和sy开始,到img的右下角结束。
sHeight: 可选 需要绘制到目标上下文中的,img的矩形(裁剪)选择框的高度。
dx: img 的左上角在目标canvas上 X 轴坐标。
dy: img的左上角在目标canvas上 Y 轴坐标。
dWidth:可选 img在目标canvas上绘制的宽度。 允许对绘制的img进行缩放。 如果不说明, 在绘制时img宽度不会缩放。
dHeight: 可选img在目标canvas上绘制的高度。 允许对绘制的img进行缩放。 如果不说明, 在绘制时img高度不会缩放。
*/
ctx.drawImage(image, dx, dy);
ctx.drawImage(image, dx, dy, dWidth, dHeight);
ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

示例:

<img id="myImg" src='./xx.webp'  width="300" height="227"/>
const myImg = document.getElementById('myImg')
ctx.drawImage(myImg,50, 300, 200,200, 100, 100, 100, 100)

效果:

image.png

ellipse()

绘制椭圆,IE 浏览器不支持,Edge13+才支持。

/**
x: 圆心的x轴坐标。
y: 圆心的y轴坐标。
radiusX: 椭圆长轴的半径。
radiusY: 椭圆短轴的半径。
rotation: 椭圆的旋转角度,以弧度表示。
startAngle: 将要绘制的起始点角度,从 x 轴测量 单位弧度。
endAngle: 椭圆有绘制结束点角度,单位弧度。
anticlockwise: 可选 true:逆时针放心绘制 false: 顺时针方向绘制
*/
ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);

示例:

// 如果长轴和短轴半径设置一样将会出现一个常规的⚪形
ctx.ellipse(150, 150, 200, 100, 45, 10, 45)
ctx.stroke()

效果:

image.png

fill()

路径填充

/**
path: 可选, 需要填充的路径
fillRule: 决定点是在路径内还是路径外,nonzero-默认值,evenodd 
*/
ctx.fill(path, fillRule);

示例:

ctx.moveTo(80, 80)
ctx.lineTo(100,120)
ctx.lineTo(20,280)
ctx.closePath()
ctx.stroke()
ctx.fill()

效果:

image.png

fillRect()

矩形填充方法。

/**
x: 矩形的起点 x 轴坐标
y: 矩形的起点 y 轴坐标
width: 矩形的宽度
height: 矩形的高度
*/
ctx.fillRect(x, y, width, height)

示例:

// 画布一个 王 字
ctx.fillRect(50,30,80,5)
ctx.fillRect(85,30,5,70)
ctx.fillRect(62,60,50,5)
ctx.fillRect(40,100,100,5)

效果:

image.png

fillText()

填充文字绘制文本。

/**
text: 文本信息。
x: 文本起始点 x 轴坐标。
y: 文本起始点 y 轴坐标。
maxWidth: 可选,绘制的最大宽度
*/
ctx.fillText(text, x, y, [maxWidth]);

示例:

ctx.font = "32px SimSun";
ctx.fillText("你好", 50, 100);

效果:

image.png

getImageData()

返回一个ImageData对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示。

/**
x: 被提取的图像数据矩形区域的左上角 x 坐标。
y: 被提取的图像数据矩形区域的左上角 y 坐标。
width: 被提取的矩形区域宽度。
height: 被提取的矩形区域高度。
*/
ctx.getImageData(x, y, width, height)

示例:

// 本地运行 html 文件不生效 起个服务运行看效果
const myImg = document.getElementById('myImg1')
ctx.drawImage(myImg,0, 0, 300,300)
​
let imgData = ctx.getImageData(50, 180, 100,50)
console.log(imgData);
const imgDataLength = imgData.data.length
for (var index = 0; index < imgDataLength; index += 4) {
    var r = imgData.data[index];
    var g = imgData.data[index + 1];
    var b = imgData.data[index + 2];
    var gray = r * 0.299 + g * 0.587 + b * 0.114
    console.log(gray);
    imgData.data[index] = gray;
    imgData.data[index + 1] = gray;
    imgData.data[index + 2] = gray;
}
// 更新新数据
ctx.putImageData(imgData, 50, 184);

getLineDash()

获取当前线段样式的方法。

// 返回值是数组
ctx.getLineDash();

getTransform()

获取当前被应用到上下文的转换矩阵。

// 返回值是一个 DOMMatrix 对象
ctx.getTransform();

isPointInPath()

检测当前路径种是否包含某一个点

/**
x:用来检测的点的横坐标。
y:用来检测的点的纵坐标。
fillRule:填充规则。用来确定一个点实在路径内还是路径外。可选值包括:
        nonzero:非零规则,此乃默认规则。
        evenodd:奇偶规则。
path指Path2D对象。
*/
// 方法返回Boolean值。
ctx.isPointInPath(x, y);
ctx.isPointInPath(x, y, fillRule);
// 以下语法ie 不支持
ctx.isPointInPath(path, x, y);
ctx.isPointInPath(path, x, y, fillRule);

示例:

ctx.rect(20, 10, 200, 200);
ctx.stroke();
console.log(ctx.isPointInPath(20, 10)); // true

isPointInStroke()

检测一个点是否在路径的描边线上。

/**
x: 检测点 x 轴坐标
y: 检测点 y 轴坐标
path: path2D 路径
*/
// 返回值:Boolean
ctx.isPointInStroke(x, y);
ctx.isPointInStroke(path, x, y);

示例

ctx.rect(20, 10, 200, 200);
ctx.stroke();
console.log(ctx.isPointInStroke(20, 10)); // true

lineTo()

连接当前子路径点和 lineTo() 指定的点。

// 参数 x,y 轴坐标
ctx.lineTo(x, y);

示例:

//  使用 beginPath() 绘制路径的起始点, 使用 moveTo()移动画笔, 使用 stroke() 方法真正地画线。
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(200, 200);
ctx.stroke();

效果:

image.png

measureText()

测量文本信息返回一个TextMetrics 对象包含的信息(例如它的宽度)。

// 参数需要测量的 str
ctx.measureText(text);

示例:

console.log(ctx.measureText("foo"))

moveTo()

表示路径绘制的起始点。

// 参数表示 x,y 轴坐标
ctx.moveTo(x,y)

putImageData()

将数据从已有的 ImageData 对象绘制到位图的方法。 如果提供了一个绘制过的矩形,则只绘制该矩形的像素。此方法不受画布转换矩阵的影响。

/**
imageData: 包含像素值的数组对象。
dx: 源图像数据在目标画布中的位置偏移量(x 轴方向的偏移量)。
dy: 源图像数据在目标画布中的位置偏移量(y 轴方向的偏移量)。
dirtyX: 可选 在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(x 坐标)。
dirtyY: 可选 在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(y 坐标)。
dirtyWidth: 可选 在源图像数据中,矩形区域的宽度。默认是图像数据的宽度。
dirtyHeight: 可选 在源图像数据中,矩形区域的高度。默认是图像数据的高度。
*/
ctx.putImageData(imagedata, dx, dy);
ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

示例:

// 起服务运行本地文件
<img id="myImg1" src='./xx.webp'  width="300" height="227"/>
<img id="myImg2" src='./123.jfif' width="300" height="200" alt=""><canvas id="tutorial" width="300" height="300">
    你的浏览器不支持 canvas,请升级你的浏览器。
</canvas>
<canvas id="tutorial2" width="300" height="300">
    你的浏览器不支持 canvas,请升级你的浏览器。
</canvas>
const myImg1 = document.getElementById('myImg1')
const myImg2 = document.getElementById('myImg2')
ctx.drawImage(myImg2, 0,0,300,200)
const canvas2 = document.getElementById('tutorial2');
let ctx2 = canvas2.getContext('2d');
// 绘制替换图
ctx2.drawImage(myImg1, 0, 0, 300, 200)
let myImgData = ctx2.getImageData(0, 0, 300, 200)
ctx.putImageData(myImgData, 0, 0, 100, 50, 100, 100)

效果:

image.png

quadraticCurveTo()

用来绘制二次贝塞尔曲线,第一个点是控制点,第二个是终点,起点是当前路径的最新点,可以使用 moveTo() 方法进行改变。

// cpx, cpy 控制点x,y轴, x,y 终点的坐标
ctx.quadraticCurveTo(cpx, cpy, x, y);

示例:

ctx.beginPath()
ctx.moveTo(80, 100)
ctx.quadraticCurveTo(150, 210, 280, 190)
ctx.stroke()

效果:

image.png

rect()

绘制矩形路径的方法,和arc()ellipse()方法是一样的。需要你需要填充,还需要执行fill()方法,如果要描边,还需要执行stroke()方法。实际上,对于矩形,填充和描边有现成的方法,这个是为矩形独有的,为fillRect()strokeRect()

/**
x: 矩形起点的 x 轴坐标。
y: 矩形起点的 y 轴坐标。
width: 矩形的宽度。
height: 矩形的高度。
*/
rect(x, y, width, height)

示例:

ctx.rect(100,100,100,100)
ctx.stroke()

效果:

image.png

restore()

状态回退,如果没有保存状态,将不做任何改变。

ctx.restore();

示例:

// 保存一下初始状态
ctx.save()
ctx.fillStyle = '#ccc'
ctx.fillRect = '100,100,50,50'
// 不执行会出现两个灰色方块
ctx.restore()
ctx.fillRect(150,150,50,50)

效果:

image.png

rotate()

给画布添加旋转矩阵,顺时针放心,单位是弧度。

// angle 顺时针旋转的弧度。如果你想通过角度值计算,可以使用公式: degree * Math.PI / 180 。
ctx.rotate(angle)

示例:

ctx.rotate(60*Math.PI / 180)
ctx.font = '24px Songti'
ctx.fillText('我是王大锤', 50, 0)
// 重置当前的变换矩阵为初始态
ctx.setTransform(1, 0, 0, 1, 0, 0);

效果:

image.png

save()

保存当前画布状态。

scale()

缩放 canvas 的坐标系,只影响坐标,之后的绘制会受此方法影响,之前已经绘制好的效果不会有任何变化。

/**js
x: canvas 坐标系水平缩放的比例。支持小数,-1代表水平翻转。
y: canvas 坐标系垂直缩放的比例。支持小数,-1代表垂直翻转。
*/
ctx.scale(x, y)

示例:

 ctx.fillRect(10, 10, 10, 10);
// 缩放
ctx.scale(10, 3);
// 再次绘制
ctx.fillRect(10, 10, 10, 10);
// 恢复坐标系
ctx.setTransform(1, 0, 0, 1, 0, 0);

效果:

image.png

setLineDash()

设置虚线样式。

// arr: 数组 [虚线的实现长度, 透明部分长度] 如果是控制则表示是实线
ctx.setLineDash(arr)

示例:

ctx.beginPath()
ctx.setLineDash([10,20,30,40])
ctx.moveTo(50,50)
ctx.lineTo(300,50)
ctx.stroke()

效果:

image.png

setTransform()

使用单位矩阵重新覆盖当前坐标系。

/**
a (m11)水平缩放。
b (m12)垂直倾斜。
c (m21)水平倾斜。
d (m22)垂直缩放。
e (dx)水平移动。
f (dy)垂直移动。
*/
ctx.setTransform(a,b,c,d,e,f)

stroke()

对路径开始绘制描边。

ctx.stroke()

strokeRect()

绘制矩形。

/**
x: 描边矩形的起点x轴坐标。
y: 描边矩形起点的Y轴坐标
width:宽
height:高
*/
ctx.strokeRect(x, y, width, height)

示例:

ctx.strokeStyle = 'red'
ctx.lineWidth = 10
ctx.strokeRect(50,50,100,100)

效果:

image.png

strokeText()

实现文字描边效果。

/**
text: 文字,
xy轴坐标
*/
ctx.strokeText(text,x,y)

示例:

ctx.font='32px Songti'
ctx.strokeText('王小锤',50,50)

效果:

image.png

transform()

对当前坐标系进行进一步的变换,实现旋转、拉伸、位移、缩放的效果。

/**
a: 水平缩放。
b: 水平斜切。
c: 垂直斜切。
d: 垂直缩放。
e: 水平位移。
f: 垂直位移。
*/
ctx.transform(a,b,c,d,e,f)

示例:

ctx.transform(1, 1, 0, 1, 0, 0);
ctx.fillStyle = 'red'
ctx.fillRect(10, 10, 100, 100);

效果:

image.png

translate()

对当前网格添加平移变换的方法。

image.png

/**
x: 坐标系水平位移的距离。
y: 坐标系垂直位移的距离。
*/
ctx.translate(x,y)

示例:

ctx.translate(50, 50);
ctx.fillRect(0,0,100,100);
ctx.setTransform(1, 0, 0, 1, 0, 0);

点赞支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。

11.png

往期精彩推荐

不懂 seo 优化?一篇文章帮你了解如何去做 seo 优化

canvas 爬坑路【属性篇】

【实战篇】微信小程序开发指南和优化实践

聊一聊移动端适配

前端性能优化实战

聊聊让人头疼的正则表达式

获取文件blob流地址实现下载功能

Vue 虚拟 DOM 搞不懂?这篇文章帮你彻底搞定虚拟 DOM

Git 相关推荐

通俗易懂的 Git 入门

git 实现自动推送

我在工作中是如何使用 git 的

面试相关推荐

前端万字面经——基础篇

前端万字面积——进阶篇

更多精彩详见:个人主页