关键是要把存放绘制的信息放到一个二维数组中:
绘制时最好不要用定时器进行定时绘制,因为会卡顿,
最好使用 requestAnimationFrame 这个原生js的api方法,
因为是以帧的间隔绘制,所以会看起来流畅
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
.container {
width: 100%;
padding: 20px 0;
display: flex;
justify-content: center;
align-items: center;
}
.canvas {
margin: 0 auto;
border: 1px solid #878484;
background-color: #ccc;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<input type="color" name="" class="js-color-picker" />
</div>
<div class="container">
<canvas class="js-canvas canvas"></canvas>
</div>
<script src="./1.js"></script>
</body>
</html>
js代码部分
/**
* @author: zhangcunxia
* @email: <EMAIL>
* @createTime: 2021-07-20 14:59:59
* @description: canvas绘制个性签名 里面的单位不需要更新,因为都是 已经乘过了 devicePixelRatio (dpr)px,所以不用考虑
* @updateTime: 2021-07-20 14:59:59
* @version: 1.0.0
* @copyright: Copyright (c) 2021
* @license: MIT
*
*/
const colorPicker = document.querySelector(".js-color-picker");
const cvs = document.querySelector(".js-canvas");
const ctx = cvs.getContext("2d");
function init() {
const w = 500;
const h = 400;
// devicePixelRatio 设备像素比,用于解决高清屏绘制模糊问题, 是一个全局属性,可以直接使用
cvs.width = w * devicePixelRatio;
cvs.height = h * devicePixelRatio;
cvs.style.width = w + "px";
cvs.style.height = h + "px";
}
init();
class Line {
constructor(startX, startY, endX, endY, color) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
this.color = color || "#000";
}
draw() {
ctx.beginPath();
ctx.moveTo(this.startX, this.startY);
ctx.lineTo(this.endX, this.endY);
ctx.strokeStyle = this.color;
ctx.stroke();
}
}
// 用于存放所有的线段
let lines = [];
// 用于存放鼠标按下并抬起完整过程的次数
let count = 0;
// function draw() {
// ctx.clearRect(0, 0, cvs.width, cvs.height);
// for (let i = 0; i < lines.length; i++) {
// lines[i].draw();
// }
// }
// const line = new Line(100, 100, 200, 200, "red");
// line.draw();
cvs.onmousedown = function (event) {
const _startX = event.clientX - cvs.offsetLeft;
const _startY = event.clientY - cvs.offsetTop;
const _inLines = [];
count++;
cvs.onmousemove = function (event) {
const _endX = event.clientX - cvs.offsetLeft;
const _endY = event.clientY - cvs.offsetTop;
if (_inLines.length === 0) {
const _inLine = new Line(
_startX,
_startY,
_endX,
_endY,
colorPicker.value
);
_inLines.push(_inLine);
} else {
const _inLine = new Line(
_inLines[_inLines.length - 1].endX,
_inLines[_inLines.length - 1].endY,
_endX,
_endY,
colorPicker.value
);
_inLines.push(_inLine);
}
lines.push(_inLines);
};
cvs.onmouseup = function () {
cvs.onmousemove = null;
cvs.onmouseup = null;
};
};
function drawLines() {
// 因为画的动作是不断进行的,所以监听并绘制每帧位置
// requestAnimationFrame 用于动画效果,每秒调用 60 次,每帧绘制一次
// 这里使用 requestAnimationFrame 绘制,可以保证动画效果流畅
// 也可以使用 setInterval 绘制,但会导致动画卡顿
// 也可以使用 setTimeout 绘制,但会导致动画效果不流畅
// 计算机性能损耗极小,动画效果不会影响到用户体验
requestAnimationFrame(drawLines);
ctx.clearRect(0, 0, cvs.width, cvs.height);
for (let line of lines) {
for (let item of line) {
// 因为数组里的是 Line 对象,所以可以直接调用 draw 方法
item.draw();
}
}
}
drawLines();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。