canvas基础介绍
canvas是啥,做啥用基本就不介绍,下面MDN解释可以看看
废话不多说,下面我直接开始介绍一些canvas最基础使用以及一些应用场景
canvas基础使用
关于canvas使用,我自己总结了四步走,可以快速应用canvas,当然一切的开始都要从canvas节点<canvas id="myCanvas">
,获取开始
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d"); // 返回canvas 的上下文,相当于canvas的一个实例
ok开始四步实操:
第一步:ctx.beginPath() 开始绘制;
- 绘制不同路径,最好都以beginPath开始,否则会被之前的绘制方式影响
第二步:moveTo() 绘制开始的点、lineTo()绘制结束的点
- 通常moveTo和lineTo组合使用
- moveTo也可以和塞贝尔曲线绘制bezierCurveTo等
第三步:以stroke(绘制路径、线条)或者fill(填充) 完成绘制
第四步:ctx.closePath()关闭绘制
canvas基础样式配置
// 画圆润的5px宽的线条配置
ctx.value.strokeStyle = "#55FF7A";
ctx.value.lineCap = "round";
ctx.value.lineJoin = "round";
ctx.value.globalAlpha = 0.5;
ctx.value.lineWidth = 5;
canvas四部实操基本绘制
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");ctx.beginPath();
ctx.moveTo(50, 50); // 开始绘制第一条子路径
ctx.lineTo(200, 50);
ctx.stroke();
ctx.closePath()
canvas其他应用场景
下面总结了博主用到过的四个canvas使用场景,欢迎评论提问~
1、canvas截图
绘制图很简单,只用到一个drawImage
API即可
drawImage
可以在画布中绘制一张图像- 第一个参数可以是绘制到上下文的元素。允许任何的画布图像源,例如:HTMLImageElement、SVGImageElement、HTMLVideoElement、HTMLCanvasElement、ImageBitmap、OffscreenCanvas 或 VideoFrame。
- 二三参数则为绘制的起始坐标,四五参数则为绘制的图大小
下面案例则是绘制video第一秒的帧图片
const canvas = document.getElementById("myCanvas");
const curPlayVideo = document.getElementById("video");
curPlayVideo.currentTime = 1000
const ctx = canvas.getContext("2d");
const width = curPlayVideo.videoWidth;
const height = curPlayVideo.videoHeight;
ctx.drawImage(curPlayVideo, 0, 0, width, height); //绘制视频
2、贝塞尔曲线
绘制贝塞尔曲线用到的相关API:
.bezierCurveTo
:是用于绘制三段式的贝塞尔曲线,参数如下- 该方法需要三个点:前两个点是控制点,第三个点是结束点
- 起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 moveTo() 进行修改
.arc
:是用于绘制小点的,参数如下- 用于将一个圆弧添加到当前子路径中
- arc() 方法创建一个以坐标 (x, y) 为中心,以 radius 为半径的圆弧。
- 路径从 startAngle 开始,到 endAngle 结束,路径方向由 counterclockwise 参数决定(默认为顺时针方向)。
// bezierCurveTo、arc参数
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
arc(x, y, radius, startAngle, endAngle, counterclockwise)
arc(x, y, 2, 0, 2 * Math.PI) // 绘制一个2px半径的圆
绘制贝塞尔曲线代码
const canvas = document.getElementById("myCanvas");const ctx = canvas.getContext("2d");const BEZIER_CURVE_HANDLER_RATE = 0.42; // 贝塞尔曲率手柄控制点的相对位置const CANVAS_PADDING = 10; // 画布安全距离const CANVAS_WIDTH = 400;const CANVAS_HEIGHT = 300;const getControllPoint = (start, end) => {const xDelta = +end.x - +start.x;return [// cp1{ x: +start.x + BEZIER_CURVE_HANDLER_RATE * xDelta, y: start.y },// cp2{ x: +end.x - BEZIER_CURVE_HANDLER_RATE * xDelta, y: end.y },];};function drawBezierCurveBetween(ctx,start,end,) {const [cp1, cp2] = getControllPoint(start, end);// Cubic Bézier curvectx.beginPath();ctx.moveTo(+start.x, +start.y);ctx.bezierCurveTo(+cp1.x, +cp1.y, +cp2.x, +cp2.y, +end.x, +end.y);ctx.stroke();// Start and end pointsctx.fillStyle = 'red';ctx.beginPath();ctx.arc(+start.x, +start.y, 2, 0, 2 * Math.PI); // Start pointctx.arc(+end.x, +end.y, 2, 0, 2 * Math.PI); // End pointctx.fill();ctx.fillText(`(${end.coordinateX}, ${end.coordinateY})`, +end.x - 30, +end.y - 10);}drawBezierCurveBetween(ctx, { x: 10, y: 10 }, { x: 100, y: 100, coordinateX: 100, coordinateY: 100 })drawBezierCurveBetween(ctx, { x: 100, y: 100 }, { x: 150, y: 150, coordinateX: 150, coordinateY: 150 })drawBezierCurveBetween(ctx, { x: 150, y: 150 }, { x: 250, y: 100, coordinateX: 250, coordinateY: 100 })
这是大概效果
3、根据图片信息,反转图片颜色
大概思路
- 首先使用使用API
drawImage
绘制图片 - 在根据
getImageData
获取图片的像素信息,便利像素再反转rgb的颜色 - 最后使用
putImageData
绘制反转过后的图片
使用API参数详解:
getImageData()
返回一个 ImageData 对象,用于描述 canvas 指定区域的隐含像素数据。
.putImageData()
方法用于将数据从已有的 ImageData 对象绘制到画布上
ctx.getImageData(sx, sy, sw, sh) // 前两参数是图片起始坐标,后来参数是图片宽高
ctx.putImageData(imageData, dx, dy) // 第一个参数是getImageData获取的data,二三参数是起始坐标
绘制代码
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const img = document.getElementById("img");
ctx.drawImage(img, 0, 0);
const imgData=ctx.getImageData(0,0,c.width,c.height);// invert colors
for (var i=0;i<imgData.data.length;i+=4){imgData.data[i]=255-imgData.data[i];imgData.data[i+1]=255-imgData.data[i+1];imgData.data[i+2]=255-imgData.data[i+2];imgData.data[i+3]=255;}
ctx.putImageData(imgData,0,0);
4、画一个以圆心为起点的平均射线
- 100毫秒画一条,基本按照博主四步走理论
function drawRadial(x0, y0, r, angle) {r = r || 10;angle = angle || 10;var len = 360 / angle;var radian = (2 * Math.PI * angle) / 360;for (var i = 1; i <= len; i++) {(function (j) {setTimeout(function timer() {x1 = x0 + r * Math.cos(radian * j);y1 = y0 + r * Math.sin(radian * j);ctx.beginPath();ctx.moveTo(x0, y0);ctx.lineTo(x1, y1);ctx.stroke();}, j * 100);})(i);}
}
drawRadial(100, 100, 50, 10);
最后效果
其他
博主用过的canvas插件
插件html2canvas
,可以制定html节点使用canvas绘制成图片
- 只要指定节点dom元素即可绘制
- 需要注意一点是每个设备像素不一样,所以绘制的时候设置1.5倍的像素比,确保绘制图片的清晰度
具体代码实现
import html2canvas from 'html2canvas'const getCanvasToImage = async () => {canCopyPoster.value = falseconst dom = document.querySelector('#dom')// 这里绘制图大小根据设备比例来const scale = window.devicePixelRatio * 1.5const options = {useCORS: true,allowTaint: false,backgroundColor: 'rgba(0,0,0,0.7)',scale,}const canvas = await html2canvas(dom, options)posterUrl.value = canvas.toDataURL() // 即可得到html节点图片}
常用的canvas API了解
一些常用的API:
fillStyle
:设置填充颜色或渐变。
strokeStyle
:设置描边颜色。
lineWidth
:设置线宽。
lineCap、lineJoin
:分别设置线条的末端样式和两条线相交时的形状。
beginPath()、closePath()
:分别用于开始一个新的路径或完成当前路径。
moveTo()、lineTo()
:分别用于移动到某个点并绘制直线到另一个点。
arc()、arcTo()
:用于绘制圆弧和圆角矩形。
fill()、stroke()
:分别用于填充和描边当前路径。
clearRect()
:清除指定矩形区域。
canvas的其他API我就不过多介绍了,感兴趣的可以去看看官网
MDN:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/canvas