Canvas 究竟是个啥
canvas的英文意思就是画布,在我们这儿canvas其实一个HTML5标签,用来定义图形,HTML5标签只是图形容器,我们需要使用脚本来绘制图形;如果我们不使用canvas,会操作大量的DOM,会消耗大量性能,而canvas不会;下面的例子可实现在PC端在移动端像画板一样写字
实际运用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas能实现划线的画板</title>
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
canvas {
border:1px solid red;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById("canvas");
if (canvas.getContext) {
const cvs = canvas.getContext("2d");
console.log(cvs);
}
</script>
</body>
</html>

- 从以上代码可以看到canvas并没有设置宽度和高度,但是cavas宽高却不是0,这是因为当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。另外需要特别注意的时候,如果我们要改变canvas的宽度与高度,要使用width和height属性来改变,而不是css方式改变,如果使用css方式改变宽高,图像会出现扭曲的现象;
- canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。getContext方法是用来获得渲染上下文和它的绘画功能。我们可以通过打印,可以看到anvasRenderingContext2D对象具体内容
- 把画布大小变为屏幕大小
<script>
const canvas = document.getElementById("canvas");
// 设置canvas宽高
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
if (canvas.getContext) {
const cvs = canvas.getContext("2d");
}
</script>
- 绘画圆点
const canvas = document.getElementById("canvas");
// 设置canvas宽高
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
if (canvas.getContext) {
const ctx = canvas.getContext("2d");
// 新建一条路径
ctx.beginPath();
// 绘制
ctx.arc(10,10,10,0,Math.PI*2,true);
// 填充
ctx.fill();
}
- 鼠标移动哪里就有绘画,我们可以使用onmousemove
const canvas = document.getElementById("canvas");
// 设置canvas宽高
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
if (canvas.getContext) {
canvas.onmousemove = (e) => {
const ctx = canvas.getContext("2d");
// 新建一条路径
ctx.beginPath();
// 绘制
ctx.arc(e.clientX,e.clientY,10,0,Math.PI*2,true);
// 填充
ctx.fill();
}
}
- 但是以上代码有问题的点是,鼠标只要移动就会绘画,我们需要鼠标按下后拖动才绘画,我们可以设个开关controlPainting,当鼠标按下后controlPainting打开,鼠标起来后,开关关闭
- 由于触屏设备没有鼠标事件,因此要做判断;
<script>
let controlPainting = false;
const canvas = document.getElementById("canvas");
// 设置canvas宽高
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
// 判断是否触屏设备
const isTouchDevice = 'ontouchstart' in document.documentElement;
// 触屏设备
if(isTouchDevice) {
canvas.ontouchmove = (e) => {
// 新建一条路径
ctx.beginPath();
// 绘制
ctx.arc(e.targetTouches[0].clientX,e.targetTouches[0].clientY,10,0,Math.PI*2,true);
// 填充
ctx.fill();
}
}else {
// pc设备
canvas.onmousedown = (e) => {
controlPainting = true;
};
canvas.onmousemove = (e) => {
if (!controlPainting) {
return false;
}
// 新建一条路径
ctx.beginPath();
// 绘制
ctx.arc(e.clientX,e.clientY,10,0,Math.PI*2,true);
// 填充
ctx.fill();
}
canvas.onmouseup = (e) => {
controlPainting = false;
}
}
</script>

- 如上图会出现断点的现象,我们可以把画圆点换成画线
<script>
let controlPainting = false;
let posX = '';
let posY = '';
const canvas = document.getElementById("canvas");
// 设置canvas宽高
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
const ctx = canvas.getContext("2d");
ctx.lineWidth = 6;
ctx.lineCap = 'round';
// 判断是否触屏设备
const isTouchDevice = 'ontouchstart' in document.documentElement;
// 触屏设备
if(isTouchDevice) {
canvas.ontouchstart = (e) => {
posX = e.targetTouches[0].clientX;
posY= e.targetTouches[0].clientY;
};
canvas.ontouchmove = (e) => {
drawLine(posX, posY, e.targetTouches[0].clientX, e.targetTouches[0].clientY);
posX = e.targetTouches[0].clientX;
posY= e.targetTouches[0].clientY;
}
}else {
// pc设备
canvas.onmousedown = (e) => {
controlPainting = true;
posX = e.clientX;
posY= e.clientY;
};
canvas.onmousemove = (e) => {
if (!controlPainting) {
return false;
}
drawLine(posX, posY, e.clientX, e.clientY);
posX = e.clientX;
posY= e.clientY;
}
canvas.onmouseup = (e) => {
controlPainting = false;
}
}
// 画线
let drawLine = (originX, originY, finalX, finalY) => {
console.log(originX, originY, finalX, finalY)
// 新建一条路径
ctx.beginPath();
// 起点
ctx.moveTo(originX, originY);
// 终点
ctx.lineTo(finalX, finalY);
// 填充
ctx.stroke();
}
</script>

最后经过修改后,就非常流畅了;