之前写了一篇随笔是讲 fabric.js 的,基于vue的,查看:https://www.cnblogs.com/reround/p/11468844.html
如果不基于vue用js也是可以实现的
代码如下,直接copy到html文件里就可以,无需加载其他插件,代码里都有注释
<!doctype html> <html> <head> <meta charset="utf-8"> <title>js画板</title> <style> * { margin: 0; padding: 0; } html, body, .container { height: 100%; } #controls { padding-left: 20px; height: 60px; line-height: 60px; } canvas { border: 1px solid #ccc; margin-left: 20px; } #controls li { list-style: none; display: inline-block; margin-right: 10px; } #img{ width: 1000px; height: 400px; background: #eee; display: inline-block; margin-left: 20px; } .word{ margin: 10px 0 10px 20px; } </style> </head> <body> <div class="container"> <ul id="controls"> <li> <label for="shape" class="label">选择形状 : </label> <select id="shape"> <option value="rect">矩形</option> <option value="line">直线</option> <!--<option value="circle">内切圆</option>--> <option value="circle">圆</option> <!--<option value="circle2">中心圆</option>--> <option value="poly">多边形</option> <option value="pen">铅笔</option> <option value="eraser">橡皮擦</option> </select> </li> <li> <label for="color" class="label">选择颜色 : </label> <input type="color" id="color" value="#ff0000"> </li> <li> <label for="color" class="label">选择线宽 : </label> <input type="number" id="width" value="1" step="1" min="2" max="20"> </li> <li> <label for="shape" class="label">选择方式 : </label> <select id="style"> <option value="stroke">描边</option> <option value="fill">填充</option> </select> </li> <li> <label for="side" class="label">选择边数 : </label> <input type="number" id="side" value="3" min="3" max="20"> </li> <li> <button id="redo">撤销</button> <button id="clear">清空</button> <button id="save">保存</button> </li> </ul> <div class="word">canvas面板:</div> <canvas width="1000px" height="400px"></canvas> <div class="word">显示保存的图片:</div> <img src="" id="img" alt="" /> </div> <script> var canvas = document.querySelector("canvas"); var canvasObj = canvas.getContext("2d"); var shape = document.querySelector("#shape"); var color = document.querySelector("#color"); var width = document.querySelector("#width"); var style = document.querySelector("#style"); var side = document.querySelector("#side"); var redo = document.querySelector("#redo"); var save = document.querySelector("#save"); var clear = document.querySelector("#clear"); var data = []; var s = "rect"; shape.onchange = function() { //获取形状 s = this.value; }; var c = "#f00"; color.onchange = function() { //获取颜色 c = this.value; }; var w = "2"; width.onchange = function() { //获取宽度 w = this.value; }; var st = "stroke"; style.onchange = function() { //获取绘画方式 st = this.value; }; var sd = "3"; side.onchange = function() { //获取边数 sd = this.value; }; canvas.onmousedown = function(e) { //canvas上按下鼠标事件 var ox = e.offsetX; var oy = e.offsetY; var draw = new Draw(canvasObj, { color: c, width: w, style: st, side: sd }); if(s === "pen") { canvasObj.beginPath(); canvasObj.moveTo(ox, oy); } canvas.onmousemove = function(e) { //移动事件 var mx = e.offsetX; var my = e.offsetY; if(s !== "eraser") { canvasObj.clearRect(0, 0, 1000, 400); if(data.length !== 0) { canvasObj.putImageData(data[data.length - 1], 0, 0, 0, 0, 1000, 400); //将数据添加到画布中 } } draw[s](ox, oy, mx, my, sd); }; document.onmouseup = function() { data.push(canvasObj.getImageData(0, 0, 1000, 400)); //获取画布中的数据 canvas.onmousemove = null; document.onmouseup = null; } }; redo.onclick = function() { //撤回 if(data.length == 0) { alert("没有可以撤销的内容了"); return; } canvasObj.clearRect(0, 0, 1000, 400); data.pop(); if(data.length == 0) { return; } canvasObj.putImageData(data[data.length - 1], 0, 0, 0, 0, 1000, 400); }; save.onclick = function() { //保存 var r = canvas.toDataURL(); document.getElementById('img').src = r }; clear.onclick = function() { //清除 canvasObj.clearRect(0, 0, 1000, 400); data = []; } class Draw { constructor(canvasObj, option) { this.canvasObj = canvasObj; this.color = option.color; this.width = option.width; this.style = option.style; } init() { //初始化 this.canvasObj.strokeStyle = this.color; this.canvasObj.fillStyle = this.color; this.canvasObj.lineWidth = this.width; } rect(ox, oy, mx, my) { this.init(); this.canvasObj.beginPath(); this.canvasObj.rect(ox, oy, mx - ox, my - oy); this.canvasObj[this.style](); } line(ox, oy, mx, my) { this.init(); this.canvasObj.beginPath(); this.canvasObj.moveTo(ox, oy); this.canvasObj.lineTo(mx, my); this.canvasObj.stroke(); } circle(ox, oy, mx, my) { //圆 this.init(); this.canvasObj.beginPath(); var r = Math.sqrt(Math.pow(mx - ox, 2) + Math.pow(my - oy, 2)); this.canvasObj.arc(ox, oy, r, 0, 2 * Math.PI); this.canvasObj[this.style](); } poly(ox, oy, mx, my, sd) { this.init(); this.canvasObj.save(); canvasObj.translate(ox, oy); this.canvasObj.rotate(Math.PI / 2); var angle = Math.PI / sd; var r = Math.sqrt(Math.pow(mx - ox, 2) + Math.pow(my - oy, 2)); var x = Math.cos(angle) * r; var y = Math.sin(angle) * r; this.canvasObj.beginPath(); this.canvasObj.moveTo(x, y); for(var i = 0; i < sd; i++) { this.canvasObj.lineTo(x, -y); this.canvasObj.rotate(-angle * 2) } this.canvasObj[this.style](); this.canvasObj.restore() } pen(ox, oy, mx, my) { this.init(); this.canvasObj.lineTo(mx, my); this.canvasObj.stroke(); } eraser(ox, oy, mx, my) { console.log(canvas.style) console.log(canvas.style.cursor) this.canvasObj.clearRect(mx, my, 20, 20); } } </script> </body> </html>