HTML5 <canvas> 标签用于绘制图像(通过脚本,通常是 JavaScript,不过,<canvas> 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务。getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。完整的 getContext("2d") 对象属性和方法,可用于在画布上绘制文本、线条、矩形、圆形等等。当然了,当我们在画布上画完以后,或者在画布上有一点小失误的时候,我们就可以用到下边的代码了,可以帮您解决这个问题。
html样式
<button id="clear">清除</button>
<button id="revoke">撤销</button>
<button id="save">保存</button>
<button id="Anti-revocatio">反撤销</button>
//向 HTML5 页面添加 canvas 元素。规定元素的 id、宽度和高度:
<canvas id="canvas" width="800px" height="800px"></canvas>
canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:代码如下
// 获取所有元素
var canvas = document.getElementById('canvas');
var clear = document.getElementById('clear');
var revoke = document.getElementById(revoke');
var eraser = document.getElementById('eraser');
var save= document.getElementById('save');
var Anti-revocatio = document.getElementById('Anti-revocatio');
var color = document.getElementById('color');
创建 context 对象:
var ctx = canvas.getContext('2d');//画笔;
··
#####设置变量:
var phflag = false;//绘制开关
var eraserFlag = false;//橡皮擦开关
var startX = 0;//初始的坐标
var startY = 0;
var sourceArr; //设置的大数组
var popArr = []
#####从localStorage里取出大数组
var targetArr = JSON.parse(localStorage.getItem('sAllArr'));
/#####判断; 如果大数组存在且有数组,说明以前运行过,那么就重新绘制这个大数组
if (targetArr && targetArr.length >= 1) {
for (var i = 0; i < targetArr.length; i++) {
phArr(targetArr[i], ctx)
}
}
声明一个小数组
var dataArr = null;
// 橡皮擦的切换开关
eraser.onclick = function (e) {
eraserFlag = !eraserFlag
}
清除储存数据,并且清除当前画布(重新访问当前页面,相当于刷新)
clear.onclick = function (e) {
localStorage.removeItem('sAllArr');
window.history.go();
}
save.onclick = function (e) {
var a = document.createElement('a');
a.href = canvas.toDataURL('image/jpg');
a.download = '未命名.jpg';
a.click();
}
后撤一步的逻辑
revoke.onclick = function (e) {
ctx.clearRect(0, 0, 800, 800);//清除整个画布
// 取出数组删除的最后一个元素
var targetArr = JSON.parse(localStorage.getItem('sAllArr'));
var singArr = targetArr.pop();
if (singArr) {
popArr.push(singArr);
}
重新绘制画布
if (targetArr && targetArr.length >= 1) {
for (var i = 0; i < targetArr.length; i++) {
phArr(targetArr[i], ctx)
}
}
// 保存删掉一个元素的新数组,保证内存中正在操作的大数组和localStroag里的大数组同步;
localStorage.setItem('sAllArr', JSON.stringify(targetArr))
}
Anti-revocatio.onclick = function (e) {
// 取出最后一步的小数组
var endArr = popArr.pop();
if (endArr) {
// 取出大数组
var targetArr = JSON.parse(localStorage.getItem('sAllArr'));
targetArr.push(endArr);
// 清楚整个画布
ctx.clearRect(0, 0, 800, 800);
// 重绘画布
if (targetArr && targetArr.length >= 1) {
for (var i = 0; i < targetArr.length; i++) {
phArr(targetArr[i], ctx)
}
}
// 保存删掉的一个元素的新数组,保证内存中正在操作的大数组和localStorage里的大数组同步;
localStorage.setItem('sAllArr', JSON.stringify(targetArr));
}
}
重置鼠标移动的起点 开启绘制开关 准备一个新的小数组
canvas.onmousedown = function (e) {
startX = e.offsetX;
startY = e.offsetY;
phflag = true; //开启开关
dataArr = [];//新的小数组
}
绘制路径(图画单元或橡皮擦擦出单元)将鼠标移动的每一步坐标数据存入小数组;
canvas.onmousemove = function (e) {
if (phflag) {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(e.offsetX, e.offsetY);
if (eraserFlag) {
ctx.lineWidth = '20';
ctx.strokeStyle = 'purple';
} else {
ctx.lineWidth = '2';
ctx.strokeStyle = 'blue';
}
ctx.stroke();
ctx.closePath();
// 将每一对鼠标坐标信息存入小数组
dataArr.push(
{
x: e.offsetX,
y: e.offsetY,
lineWidth: ctx.lineWidth,
color: ctx.strokeStyle,
}
)
startX = e.offsetX;
startY = e.offsetY;
}
}
将大数组从localStorage中取出
canvas.onmouseup = function (e) {
sourceArr = JSON.parse(localStorage.getItem('sAllArr')) || [];
sourceArr.push(dataArr);
localStorage.setItem('sAllArr', JSON.stringify(sourceArr));
dataArr = null;
phflag = false;
}
绘制一个绘制单元,一个小数组;
function phArr(arr, ctx) {
if (arr && arr.length >= 1) {
ctx.beginPath();
ctx.moveTo(arr[0].x, arr[0].y)
for (var i = 0; i < arr.length; i++) {
ctx.lineTo(arr[i].x, arr[i].y);
}
ctx.lineWidth = arr[0].lineWidth;
ctx.strokeStyle = arr[0].color;
ctx.stroke();
ctx.closePath();
} else {
console.log('碰见一个空数组')
}
)