irpas技术客

JavaScript - canvas - 使用鼠标画线,带撤销与重做功能_光头强不在

未知 3849

文章目录 预备知识画直线项目结构HTMLCSSJavaScript效果 使用鼠标画线,带撤销与重做功能使用鼠标画线HTMLJavaScript效果 添加撤销与重做功能HTMLJavaScript效果

预备知识 画直线 项目结构

HTML

index.html 文件:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>画直线</title> <link href="css/main.css" rel="stylesheet"> </head> <body> <canvas id="canvas"></canvas> <script src="js/main.js"></script> </body> </html> CSS

main.css 文件:

#ccs { box-shadow: 0px 0px 2px 1px rgba(0, 0, 0, 0.4); } JavaScript

main.js 文件:

window.onload = (event) => { // console.log(event); main(); } function main() { const canvas = document.getElementById("canvas"); // 设置画布的宽高 canvas.width = 400; canvas.height = 400; const ctx = canvas.getContext("2d"); // 画直线 ctx.beginPath(); ctx.moveTo(0, 0); // 画笔的起点 ctx.lineTo(100, 100); // 画笔的终点,第一个参数表示向左移动 100 像素,,第二个参数表示向下移动 100 像素 ctx.stroke(); } 效果

使用鼠标画线,带撤销与重做功能 使用鼠标画线 HTML

index.html 文件:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>使用鼠标画线</title> <link href="css/main.css" rel="stylesheet"> </head> <body> <canvas id="canvas"></canvas> <script src="js/main.js"></script> </body> </html> JavaScript

main.js 文件:

window.onload = (event) => { // console.log(event); main(); } function main() { const canvas = document.getElementById("canvas"); // 设置画布的宽高 canvas.width = 400; canvas.height = 400; const ctx = canvas.getContext("2d"); if (!ctx) return; const MOUSE_LEFT_BUTTON = 0; // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button let isDrawing = false; let x = 0; let y = 0; canvas.addEventListener("mousedown", (event) => { // console.log(event); if (event.button !== MOUSE_LEFT_BUTTON) { return; } x = event.layerX; y = event.layerY; isDrawing = true; }); canvas.addEventListener("mousemove", (event) => { // console.log(event); // console.log(event.layerX, event.layerY); if (event.button !== MOUSE_LEFT_BUTTON) { return; } if (isDrawing) { drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY); x = event.layerX; y = event.layerY; } }); canvas.addEventListener("mouseup", (event) => { // console.log(event); if (event.button !== MOUSE_LEFT_BUTTON) { return; } if (isDrawing) { drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY); x = 0; y = 0; isDrawing = false; } }); } function drawLine(context, strokeStyle, lineWidth, x0, y0, x1, y1) { context.beginPath(); context.strokeStyle = strokeStyle; context.lineWidth = lineWidth; context.moveTo(x0, y0); context.lineTo(x1, y1); context.stroke(); } 效果

添加撤销与重做功能 HTML

index.html 文件:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>使用鼠标画线,带撤销与重做功能</title> <link href="css/main.css" rel="stylesheet"> </head> <body> <canvas id="canvas"></canvas> <input type="button" id="undo" value="undo" /> <input type="button" id="redo" value="redo" /> <script src="js/pako.js"></script> // 压缩与解压:http://nodeca.github.io/pako/ <script src="js/main.js"></script> </body> </html> JavaScript

main.js 文件:

window.onload = (event) => { // console.log(event); main(); } function main() { const canvas = document.getElementById("canvas"); const undo = document.querySelector("#undo"); const redo = document.querySelector("#redo"); // 设置画布的宽高 canvas.width = 400; canvas.height = 400; // 禁用撤销与重做按钮 undo.disabled = true; redo.disabled = true; const ctx = canvas.getContext("2d"); if (!ctx) return; const undoHistory = []; const redoHistory = []; const MOUSE_LEFT_BUTTON = 0; // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button let isDrawing = false; let x = 0; let y = 0; // 鼠标按下事件 canvas.addEventListener("mousedown", (event) => { // console.log(event); if (event.button !== MOUSE_LEFT_BUTTON) { return; } { // 保存画布的像素数据 const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const compressed = pako.deflate(new Uint8Array(imageData.data)); // 压缩,减小存储开销 undoHistory.push(compressed); redoHistory.splice(0, redoHistory.length); // 删除所有内容 undo.disabled = false; redo.disabled = true; } { // 保存鼠标在画布中的坐标 x = event.layerX; y = event.layerY; isDrawing = true; } }); // 鼠标移动事件 canvas.addEventListener("mousemove", (event) => { // console.log(event); // console.log(event.layerX, event.layerY); if (event.button !== MOUSE_LEFT_BUTTON) { return; } if (isDrawing) { drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY); x = event.layerX; y = event.layerY; } }); // 鼠标松开事件 canvas.addEventListener("mouseup", (event) => { console.log(event); if (event.button !== MOUSE_LEFT_BUTTON) { return; } if (isDrawing) { drawLine(ctx, x, y, event.layerX, event.layerY); x = 0; y = 0; isDrawing = false; } }); undo.onclick = (event) => { // console.log(event); // 在撤销之前,保存当前画布的像素数据 { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const compressed = pako.deflate(new Uint8Array(imageData.data)); redoHistory.push(compressed); redo.disabled = false; } // 撤销 { const compressed = undoHistory.pop(); try { const decompressed = pako.inflate(compressed); // 解压 const uint8ClampedArray = new Uint8ClampedArray(decompressed); const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height); ctx.putImageData(imageData, 0, 0); } catch (error) { console.error(error); } if (undoHistory.length === 0) { undo.disabled = true; } } } redo.onclick = (event) => { // console.log(event); // 在重做之前,保存当前画布的像素数据 { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const compressed = pako.deflate(new Uint8Array(imageData.data)); undoHistory.push(compressed); undo.disabled = false; } // 重做 { const compressed = redoHistory.pop(); try { const decompressed = pako.inflate(compressed); const uint8ClampedArray = new Uint8ClampedArray(decompressed); const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height); ctx.putImageData(imageData, 0, 0); } catch (error) { console.log(error); } if (redoHistory.length === 0) { redo.disabled = true; } } } } function drawLine(context, strokeStyle, lineWidth, x0, y0, x1, y1) { context.beginPath(); context.strokeStyle = strokeStyle; context.lineWidth = lineWidth; context.moveTo(x0, y0); context.lineTo(x1, y1); context.stroke(); } 效果


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #JavaScript #canvas #使用鼠标画线 #带撤销与重做功能 #文件ampltDOCTYPE