作者:Seet琸琸 | 来源:互联网 | 2023-08-16 04:12
本文同步于个人博客:https:zhoushuo.meblog20180311drawing-borad前些天进修了HTML5的元素,本日就来实践一下,用canva
本文同步于个人博客:https://zhoushuo.me/blog/2018/03/11/drawing-borad/
前些天进修了HTML5
的
元素,本日就来实践一下,用canvas
做一个画板。
起首说一下要完成的功用:
- 切换画笔色彩
- 调整笔刷粗细
- 清空画布
- 橡皮擦擦除
- 打消操纵
- 保留成图片
- 兼容挪动端(支撑触摸)
好了,废话少说,先看终究结果:https://zhoushuozh.github.io/drawingborad
预备工作
起首,预备个容器,也就是画板了。
然后初始化js:
let canvas = document.getElementById("drawing-board");
let ctx = canvas.getContext("2d");
我想把画板做成全屏的,所以接下来设置一下canvas
的宽高。
let pageWidth = document.documentElement.clientWidth;
let pageHeight = document.documentElement.clientHeight;
canvas.width = pageWidth;
canvas.height = pageHeight;
由于部份IE不支撑canvas
,假如要兼容IE,我们能够建立一个canvas
,然后运用excanvas
初始化,针对IE加上exCanvas.js,这里我们临时先不斟酌IE。
完成一个简朴的画板
完成思绪:监听鼠标事宜,用drawCircle()
要领把纪录的数据画出来。
- 设置初始化当前画布功用为画笔状况,
painting = false
, - 当鼠标按下时(
mousedown
),把painting
设为true
,示意正在画,鼠标没松开。把鼠标点纪录下来。 - 当按下鼠标的时刻,鼠标挪动(
mousemove
)就把点纪录下来并画出来。 - 假如鼠标挪动过快,浏览器跟不上绘画速率,点与点之间会产物间隙,所以我们须要将画出的点用线连起来(
lineTo()
)。 - 鼠标松开的时刻(
mouseup
),把painting
设为false
。
代码:
let painting = false;
let lastPoint = {x: undefined, y: undefined};
//鼠标按下事宜
canvas.Onmousedown= function (e) {
painting = true;
let x = e.clientX;
let y = e.clientY;
lastPoint = {"x": x, "y": y};
drawCircle(x, y, 5);
};
//鼠标挪动事宜
canvas.Onmousemove= function (e) {
if (painting) {
let x = e.clientX;
let y = e.clientY;
let newPoint = {"x": x, "y": y};
drawLine(lastPoint.x, lastPoint.y, newPoint.x, newPoint.y,clear);
lastPoint = newPoint;
}
};
//鼠标松开事宜
canvas.Onmouseup= function () {
painting = false;
}
// 画点函数
function drawCircle(x, y, radius) {
ctx.save();
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
}
// 划线函数
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.closePath();
}
橡皮擦功用
完成思绪
- 猎取橡皮擦元素
- 设置橡皮擦初始状况,
clear = false
。 - 监听橡皮擦
click
事宜,点击橡皮擦,转变橡皮擦状况,clear = true
。 -
clear
为true
时,挪动鼠标运用canvas
剪裁(clip()
)擦除画布。
let eraser = document.getElementById("eraser");
let clear = false;
eraser.Onclick= function () {
clear = true;
};
...
if (clear) {
ctx.save();
ctx.globalCompositeOperation = "destination-out";
ctx.stroke();
ctx.closePath();
ctx.clip();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.restore();
}
...
注重,在canvas
中的裁剪和日常平凡的裁剪功用不一样在这里,裁剪是指在裁剪地区去显现我们所画的图
兼容挪动端
完成思绪:
- 推断装备是不是支撑触摸
-
true
,则运用touch
事宜;false
,则运用mouse
事宜
代码:
...
if (document.body.ontouchstart !== undefined) {
// 运用touch事宜
anvas.Ontouchstart= function (e) {
// 最先触摸
}
canvas.Ontouchmove= function (e) {
// 最先滑动
}
canvas.Ontouchend= function () {
// 滑动完毕
}
}else{
// 运用mouse事宜
...
}
...
这里须要注重的一点是,在touch
事宜里,是经由过程.touches[0].clientX
和.touches[0].clientY
来猎取坐标的,这点要和mouse
事宜区别开。
切换画笔色彩
完成思绪:
- 猎取色彩元素节点。
- 点击色彩返回其色彩值,并赋给画布的
ctx.strokeStyle
。
代码:
let aColorBtn = document.getElementsByClassName("color-item");
for (let i = 0; i aColorBtn[i].Onclick= function () {
for (let i = 0; i activeColor = this.style.backgroundColor;
ctx.strokeStyle = activeColor;
}
}
清空画布
完成思绪:
- 猎取元素节点。
- 点击清空按钮清空canvas画布。
代码:
let reSetCanvas = document.getElementById("clear");
reSetCanvas.Onclick= function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
};
调整笔刷粗细
完成思绪:
- 建立input[type=range]
- 滑动range猎取其value值,并赋给
ctx.lineWidth
代码:
let range = document.getElementById("range");
range.Onchange= function(){
lWidth = this.value;
};
保留成图片
完成思绪:
- 猎取canvas.toDateURL
- 在页面里建立并插进去一个a标签
- a标签href即是canvas.toDateURL,并增添download属性
- 点击保留按钮,a标签触发click事宜
代码:
let save = document.getElementById("save");
save.Onclick= function () {
let imgUrl = canvas.toDataURL("image/png");
let saveA = document.createElement("a");
document.body.appendChild(saveA);
saveA.href = imgUrl;
saveA.download = "zspic" + (new Date).getTime();
saveA.target = "_blank";
saveA.click();
};
打消
完成思绪:
- 预备一个数组纪录汗青操纵
- 每次运用画笔前将当前画图外表贮存进数组
- 点击打消时,恢复到上一步的画图外表
代码:
canvas.Ontouchstart= function (e) {
// 在这里贮存画图外表
this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
saveData(this.firstDot);
...
}
let undo = document.getElementById("undo");
let historyDeta = [];
function saveData (data) {
(historyDeta.length === 10) && (historyDeta.shift()); // 上限为贮存10步,太多了怕挂掉
historyDeta.push(data);
}
undo.Onclick= function(){
if(historyDeta.length <1) return false;
ctx.putImageData(historyDeta[historyDeta.length - 1], 0, 0);
historyDeta.pop()
};
由于每次贮存都是将一张图片存入内存,对机能影响较大,所以在这里设置了贮存上限。
总结
这里用的知识点主要有:监听mouse
、touch
事宜,以及canvas
的moveTo()
、lineTo()
、stroke()
、clip()
、clearRect()
等要领。实在另有许多结果能够完成,比如说喷雾结果,蜡笔结果,艺术画结果等等。往后有时间我会继承对这个画板举行优化,增添一些新的功用,同时迎接人人留言发问或许提出批评发起。
终究代码:https://github.com/zhoushuozh/drawingborad