<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>canvas</title> </head> <style> .toolbar { width: 200px; float: left; } .canvas1 { position: absolute; left: 200px; z-index: 101; } .canvas2 { background: #03A9F4; position: absolute; left: 200px; z-index: 100; } </style> <body> <div id="toolbar" class="toolbar"> <h2>工具栏</h2> <input onclick="switchMark(1)" type="button" value="画笔" /><br /> <input onclick="switchMark(2)" type="button" value="矩形" /><br /> <input onclick="switchMark(3)" type="button" value="圆形" /><br /> <input onclick="switchMark(4)" type="button" value="文字" /><br /> <div id="inputText"> <input id="text" type="input" style=" 100px;" /> <button onclick="inputText()">确定</button><br /> </div> <input onclick="switchMark(0)" type="button" value="撤销" /><br /> </div> <canvas id="canvas1" class="canvas1" width="400px" height="400px">您的浏览器不支持画布!</canvas> <canvas id="canvas2" class="canvas2" width="400px" height="400px">您的浏览器不支持画布!</canvas> <script> var canvas1 = document.getElementById("canvas1"); var context1 = canvas1.getContext("2d"); var canvas2 = document.getElementById("canvas2"); var context2 = canvas2.getContext("2d"); var text = document.getElementById('inputText'); text.style.display = 'none'; var canvasWidth = 400; var canvasHeight = 400; // 图片索引 var canvasIndex = -1; // 图片数据 var canvasData = []; // 轨迹结束判断 var isSameMove = false; // 标注类型 var switchMarkType = null; // 鼠标按下状态 var isMouseDown = false; // 鼠标坐标 var mouseXY = { x1: 0, y1: 0, x2: 0, y2: 0 }; // 保存初始图片 canvasIndex++; canvasData.push(canvas2.toDataURL()); // 标注类型切换 function switchMark(markType) { if (markType === 0) { undo(); } if (markType !== 4) { text.style.display = 'none'; } if (switchMarkType === markType || markType === 0) { switchMarkType = null; return; } switchMarkType = markType; } // 输入文字标注 function inputText() { var str = document.getElementById('text').value; context1.font = '24px Arial'; context1.fillText(str, mouseXY.x1, mouseXY.y1); setCanvasImage(context2, canvas2, canvas1.toDataURL(), canvasWidth, canvasHeight, (url) => { context1.clearRect(0, 0, canvasWidth, canvasHeight); canvasIndex++; canvasData.push(url); }) text.style.display = 'none'; } // 撤销 function undo() { if (canvasIndex > 0) { canvasData.pop(); canvasIndex--; context2.clearRect(0, 0, canvasWidth, canvasHeight); setCanvasImage(context2, canvas2, canvasData[canvasIndex], canvasWidth, canvasHeight, (url) => { return; }); } else { console.log('不能再继续撤销了'); } } // 鼠标按下 canvas1.onmousedown = function (e) { isMouseDown = true; context1.lineWidth = '2'; context1.strokeStyle = 'red'; context1.fillStyle = 'red'; setMouseXY(true, e); // 绘制线 if (switchMarkType === 1) { context1.beginPath(); context1.moveTo(mouseXY.x1, mouseXY.y1); } // 绘制文字 if (switchMarkType === 4) { text.style.display = 'block'; } } // 鼠标向上 canvas1.onmouseup = function (e) { isMouseDown = false; if (switchMarkType === null || switchMarkType === 4) { return; } setCanvasImage(context2, canvas2, canvas1.toDataURL(), canvasWidth, canvasHeight, (url) => { context1.clearRect(0, 0, canvasWidth, canvasHeight); canvasIndex++; canvasData.push(url); }) } // 鼠标移动 canvas1.onmousemove = function (e) { if (isMouseDown) { // 清除canvas1上的图像 context1.clearRect(0, 0, canvasWidth, canvasHeight); // 绘制线 if (switchMarkType === 1) { // 记录起点坐标 setMouseXY(true, e); context1.lineTo(mouseXY.x1, mouseXY.y1); context1.stroke(); context1.save(); } // 记录终点坐标 setMouseXY(false, e); // 绘制矩形 if (switchMarkType === 2) { context1.strokeRect(mouseXY.x1, mouseXY.y1, mouseXY.x2 - mouseXY.x1, mouseXY.y2 - mouseXY.y1); } // 绘制圆形 if (switchMarkType === 3) { context1.beginPath(); var cx = (mouseXY.x1 + mouseXY.x2) / 2; var cy = (mouseXY.y1 + mouseXY.y2) / 2; var rx = Math.abs((mouseXY.x1 - mouseXY.x2) / 2); var ry = Math.abs((mouseXY.y1 - mouseXY.y2) / 2); context1.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2); context1.stroke(); } // 在canvas1上绘制图像 context1.drawImage(canvas1, 0, 0, canvasWidth, canvasHeight); } } // 根据宽高生成canvas图像 function setCanvasImage(context, canvas, base64PImg, canvasWidth, canvasHeight, callback) { let img = new Image(); img.onload = function () { context.drawImage(img, 0, 0, canvasWidth, canvasHeight); callback(canvas.toDataURL()); } img.src = base64PImg; } // 求鼠标坐标函数 function windowToCanvas(canvas, x, y) { const rect = canvas.getBoundingClientRect(); return { x: x - rect.left * (canvas.width / rect.width), y: y - rect.top * (canvas.height / rect.height) }; } // 记录坐标 function setMouseXY(start, e) { const ele = windowToCanvas(canvas1, e.clientX, e.clientY); if (start) { mouseXY.x1 = ele.x; mouseXY.y1 = ele.y; } else { mouseXY.x2 = ele.x; mouseXY.y2 = ele.y; } } </script> </body> </html>