运用Canvas和JavaScript做一个画板

本文同步于个人博客:https://zhoushuo.me/blog/2018/03/11/drawing-borad/

前些天进修了HTML5<canvas>元素,本日就来实践一下,用canvas做一个画板。

《运用Canvas和JavaScript做一个画板》

起首说一下要完成的功用:

  • 切换画笔色彩
  • 调整笔刷粗细
  • 清空画布
  • 橡皮擦擦除
  • 打消操纵
  • 保留成图片
  • 兼容挪动端(支撑触摸)

好了,废话少说,先看终究结果:https://zhoushuozh.github.io/drawingborad

预备工作

起首,预备个容器,也就是画板了。

<canvas id="drawing-board"></canvas>

然后初始化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()要领把纪录的数据画出来。

  1. 设置初始化当前画布功用为画笔状况,painting = false
  2. 当鼠标按下时(mousedown),把painting设为true,示意正在画,鼠标没松开。把鼠标点纪录下来。
  3. 当按下鼠标的时刻,鼠标挪动(mousemove)就把点纪录下来并画出来。
  4. 假如鼠标挪动过快,浏览器跟不上绘画速率,点与点之间会产物间隙,所以我们须要将画出的点用线连起来(lineTo())。
  5. 鼠标松开的时刻(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();
}

橡皮擦功用

完成思绪

  1. 猎取橡皮擦元素
  2. 设置橡皮擦初始状况,clear = false
  3. 监听橡皮擦click事宜,点击橡皮擦,转变橡皮擦状况,clear = true
  4. cleartrue时,挪动鼠标运用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中的裁剪和日常平凡的裁剪功用不一样在这里,裁剪是指在裁剪地区去显现我们所画的图

兼容挪动端

完成思绪:

  1. 推断装备是不是支撑触摸
  2. 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事宜区别开。

切换画笔色彩

完成思绪:

  1. 猎取色彩元素节点。
  2. 点击色彩返回其色彩值,并赋给画布的ctx.strokeStyle

代码:

let aColorBtn = document.getElementsByClassName("color-item");

for (let i = 0; i < aColorBtn.length; i++) {
    aColorBtn[i].onclick = function () {
    for (let i = 0; i < aColorBtn.length; i++) {
        activeColor = this.style.backgroundColor;
        ctx.strokeStyle = activeColor;
    }
}

清空画布

完成思绪:

  1. 猎取元素节点。
  2. 点击清空按钮清空canvas画布。

代码:

let reSetCanvas = document.getElementById("clear");

reSetCanvas.onclick = function () {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
};

调整笔刷粗细

完成思绪:

  1. 建立input[type=range]
  2. 滑动range猎取其value值,并赋给ctx.lineWidth

代码:

let range = document.getElementById("range");

range.onchange = function(){
    lWidth = this.value;
};

保留成图片

完成思绪:

  1. 猎取canvas.toDateURL
  2. 在页面里建立并插进去一个a标签
  3. a标签href即是canvas.toDateURL,并增添download属性
  4. 点击保留按钮,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();
};

打消

完成思绪:

  1. 预备一个数组纪录汗青操纵
  2. 每次运用画笔前将当前画图外表贮存进数组
  3. 点击打消时,恢复到上一步的画图外表

代码:

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()
};

由于每次贮存都是将一张图片存入内存,对机能影响较大,所以在这里设置了贮存上限。

总结

这里用的知识点主要有:监听mousetouch事宜,以及canvasmoveTo()lineTo()stroke()clip()clearRect()等要领。实在另有许多结果能够完成,比如说喷雾结果,蜡笔结果,艺术画结果等等。往后有时间我会继承对这个画板举行优化,增添一些新的功用,同时迎接人人留言发问或许提出批评发起。

终究代码:https://github.com/zhoushuozh/drawingborad

    原文作者:周石页
    原文地址: https://segmentfault.com/a/1190000013747671
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞