本文主要实现了canvas涂鸦功能,包括涂鸦,前进后退、清除画布以及画笔大小修改。
主要是监听鼠标按下、移动、松开事件,将鼠标按下的值赋值给moveTo的x和y值,作为起始位置。在移动事件中,将鼠标距离可视区x和y值赋给lineTo,再将路径闭合即可。
// 实现撤销和重做的功能
let canvasHistory = [];
let step = -1;
let canX;//画布左上角的x坐标
let canY;//画布左上角y坐标
/*
* canvas 画布标签
* ctx 元素的context
* undo 撤销元素id
* activeColor 画笔颜色
*/
// 实现涂鸦功能
let drawing = function(canvas, ctx, undo, activeColor){
let _ = this;
canvas.onmousedown = function(ev){
let domObj = this.getBoundingClientRect();
canX = domObj.left;//获取画布左上角的x坐标
canY = domObj.top;//获取画布左上角的y坐标
// 鼠标在canvas元素区域中的坐标之后对坐标进行了缩放,从而获得了鼠标相对于 canvas 元素绘图表面的坐标
// 处理放大缩小时,涂鸦画不上去问题(踩了好长时间的坑~~~~~)
let x = (ev.clientX - canX) * (canvas.width / domObj.width);
let y = (ev.clientY - canY) * (canvas.height / domObj.height);
// 画的时候动态修改画布颜色(默认是黑色画笔)
ctx.fillStyle = activeColor;
ctx.strokeStyle = activeColor;
ctx.beginPath();
ctx.moveTo(x,y);
canvas.onmousemove = function(ev){
let targetX = (ev.clientX - canX) * (canvas.width / domObj.width);
let targetY = (ev.clientY - canY) * (canvas.height / domObj.height);
ctx.lineWidth = _.penSize; // 画笔大小
ctx.lineTo(targetX,targetY);
ctx.stroke();
};
canvas.onmouseup = function(){
canvas.onmousemove = null;
canvas.onmouseup = null;
canvasDraw();
};
// 绘制方法
function canvasDraw() {
step++;
if (step < canvasHistory.length) {
canvasHistory.length = step; // 截断数组
}
// 添加新的绘制到历史记录
canvasHistory.push(canvas.toDataURL());
if (step > 0) {
undo.classList.add('active');
}
}
};
};
/*
* canvasHistory 存储橡皮擦历史记录数组
* eraserStep 步长
* undo 撤销元素id
* redo 再做元素id
* ctx 获取这个元素的context——图像稍后将在此被渲染
*/
let canvasUndo = async function(undo, redo, ctx, canvasId, imgSrc){
let _ = this;
if (eraserStep > 0) {
eraserStep--;
let canvasPic = new Image();
canvasPic.src = canvasHistory[eraserStep];
canvasPic.onload = function () {
ctx.drawImage(canvasPic, 0, 0);
};
undo.classList.add('active');
redo.classList.add('active');
} else if(eraserStep === 0){
eraserStep--;
canvasDrawImg(canvasId, imgSrc); // 回到画布初始状态
undo.classList.remove('active');
Message({
type: 'warning',
message: '不能再继续撤销了',
duration: 2000
});
}
};
let canvasRedo = async function(redo, ctx, canvas){
let _ = this;
if (step < canvasHistory.length - 1) {
step++;
let canvasPic = new Image();
canvasPic.src = canvasHistory[step];
canvasPic.onload = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(canvasPic, 0, 0);
};
} else {
redo.classList.remove('active');
Message({
type: 'warning',
message: '已经是最新的记录了',
duration: 2000
});
}
};
let resetEvent = async function(undo, redo, canvasId){
let _ = this;
canvasDrawImg(canvasId, _.matUrl);
canvasHistory = [];
undo.classList.remove('active');
redo.classList.remove('active');
};
// canvas上绘制画布
let canvasDrawImg = function(canvasId, imgSrc){
let canvas = document.getElementById(canvasId);
if (canvas) {
let ctx = canvas.getContext('2d');
// 画布大小宽高619.5、400px
canvas.width = 619.5;
canvas.height = 495;
ctx.clearRect(0, 0, canvas.width, canvas.height); // 在给定矩形内清空一个矩形
let img = new Image();
img.src = imgSrc;
img.setAttribute("crossOrigin",'Anonymous');
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
}
}
};
整体就这么多啦,大家看时有什么问题欢迎随时沟通