//一个简单的画板
<!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>putImageData</title> <style> body, html { margin: 0; padding: 0; } #myCanvas { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } .tools { position: fixed; top: 0; right: 0; left: 0; padding: 15px 10px; font-size: 0; background: #1a1a1a; z-index: 1; } .tool { display: inline-block; font-size: 12px; background: #eee; padding: 5px; cursor: pointer; vertical-align: middle; /* width: 40px; */ text-align: center; } .tool+.tool { margin-left: 5px; } </style> </head> <body> <div class="tools"> <div class="tool" onclick="selToolClick('line')">线</div> <div class="tool" onclick="selToolClick('rect')">矩形</div> <div class="tool" onclick="selToolClick('circle')">圆</div> <div class="tool" onclick="selToolClick('ellipse')">椭圆</div> <div class="tool" onclick="selToolClick('cloud')">云线</div> <div class="tool" onclick="selToolClick('polygon')">多边形</div> <div class="tool" onclick="exportImgData()">导出图片</div> </div> <canvas id="myCanvas"> </canvas> <script> function coord(startPoint, endPoint) { return { a: endPoint.x - startPoint.x, //x的差 b: endPoint.y - startPoint.y, //y的差 c: Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)), //两点间的距离 k: Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x) //斜率 }; } function polar(p, k) { // p 长度 // k 角度, 斜率 return { x: p * Math.cos(k), y: p * Math.sin(k) }; } class baseTool { constructor(ctx) { this.canvasContext = ctx; this.startPoint = {}; this.endPoint = {} this.points = [] } setCanvasStyle() { this.canvasContext.lineWidth = 2; this.canvasContext.strokeStyle = "blue"; this.canvasContext.fillStyle = "blue"; } drawGraph() { } } class lineTool extends baseTool { constructor(ctx) { super(ctx); } drawGraph() { this.setCanvasStyle(); this.canvasContext.beginPath(); this.canvasContext.moveTo(this.startPoint.x, this.startPoint.y); this.canvasContext.lineTo(this.endPoint.x, this.endPoint.y); this.canvasContext.stroke(); } } class rectTool extends baseTool { constructor(ctx) { super(ctx); } drawGraph() { this.setCanvasStyle(); this.canvasContext.beginPath(); this.canvasContext.rect(this.startPoint.x, this.startPoint.y, this.endPoint.x - this.startPoint.x, this.endPoint.y - this.startPoint.y); this.canvasContext.stroke(); } } class circleTool extends baseTool { constructor(ctx) { super(ctx); } drawGraph() { this.setCanvasStyle(); let _x = this.startPoint.x - this.endPoint.x; let _y = this.startPoint.y - this.endPoint.y; let r = Math.sqrt(_x * _x + _y * _y); this.canvasContext.beginPath(); this.canvasContext.arc(this.startPoint.x, this.startPoint.y, 1, 0, 2 * Math.PI); this.canvasContext.stroke(); this.canvasContext.beginPath(); this.canvasContext.arc(this.startPoint.x, this.startPoint.y, r, 0, 2 * Math.PI); this.canvasContext.stroke(); } } class ellipseTool extends baseTool { constructor(ctx) { super(ctx); } drawGraph() { this.setCanvasStyle(); this.canvasContext.beginPath(); //椭圆圆心坐标 //圆心点 let _x = (this.endPoint.x + this.startPoint.x) / 2; let _y = (this.endPoint.y + this.startPoint.y) / 2 // let radiusX = Math.abs((this.startPoint.x - this.endPoint.x) / 2); let radiusY = Math.abs((this.startPoint.y - this.endPoint.y) / 2); this.canvasContext.ellipse(_x, _y, radiusX, radiusY, 0, 0, 2 * Math.PI); this.canvasContext.stroke(); // this.canvasContext.fill(); } } class polygonTool extends baseTool { constructor(ctx) { super(ctx); this.isCloseGraph = false; this.cloudRadiusMin = 20; this.cloudRadiusMax = 30; } get allPoints() { let points = []; points.push(this.startPoint); points = points.concat(this.points); points.push(this.endPoint); return points } set allPoints(val) { } drawGraph() { this.setCanvasStyle(); this.canvasContext.beginPath(); this.canvasContext.moveTo(this.startPoint.x, this.startPoint.y); for (let i = 0; i < this.points.length; i++) { var point = { ...this.points[i] } this.canvasContext.lineTo(point.x, point.y); } this.canvasContext.lineTo(this.endPoint.x, this.endPoint.y); this.canvasContext.stroke(); } } class cloudTool extends polygonTool { constructor(ctx) { super(ctx); } drawGraph() { this.setCanvasStyle(); for (let i = 0; i < this.allPoints.length - 1; i++) { const CPoint = this.allPoints[i]; const NPoint = this.allPoints[i + 1]; const c = coord(CPoint, NPoint).c;//俩点之间的距离 const k = coord(CPoint, NPoint).k;//俩点之间的斜率 let tmpPoints = [];//俩点之间的分割点集 let tmpPoints2 = []; let index = 0; index = index + 1; tmpPoints.push({ ...CPoint }) for (let j = 0; j < Math.round((c + this.cloudRadiusMin / 2) / this.cloudRadiusMin); j++) { let newPoint = { x: this.cloudRadiusMin * Math.cos(k) + tmpPoints[index - 1].x, y: this.cloudRadiusMin * Math.sin(k) + tmpPoints[index - 1].y } tmpPoints.push({ ...newPoint }); index = index + 1; } for (let n = 0; n < tmpPoints.length; n++) { var point = { x: tmpPoints[n].x - polar(this.cloudRadiusMin / 2, k).x, y: tmpPoints[n].y - polar(this.cloudRadiusMin / 2, k).y }; tmpPoints2.push(point) } for (let m = 0; m < tmpPoints2.length - 1; m++) { const tp = tmpPoints2[m]; var c1 = coord(tmpPoints2[m], tmpPoints2[m + 1]).c;//俩点之间的距离 var x1 = polar(c1 / 2, k).x + tmpPoints2[m].x; var y1 = polar(c1 / 2, k).y + tmpPoints2[m].y; let r1 = c1 / 2 / Math.cos(30 / 180 * Math.PI); var distance = coord({ x: x1, y: y1 }, NPoint).c; var distanceHalf = distance / 2; if (m == tmpPoints2.length - 1) { this.canvasContext.beginPath(); this.canvasContext.arc(x1, y1, r1, k, k + Math.PI * 7 / 6, true); this.canvasContext.stroke(); } else { this.canvasContext.beginPath(); this.canvasContext.arc(x1, y1, r1, k, k + Math.PI * 7 / 6, true); this.canvasContext.stroke(); } } } } isNearStartPoint() { } } class Print { constructor(id) { this.id = id; this.canvas = null; this.ctx = null; this.canvasGraph = null; this.canvasGraphContext = null; this.canvasMedia = null; this.canvasMediaContext = null; this.tool = null; this.tools = [];//所有的数据 this.toolName = null; this.viewStyle = {}; this.mouse = { down: { x: null, y: null }, move: { x: null, y: null }, up: { x: null, y: null }, isMove: false } this.init(); this.bindEvent(); } init() { var height = document.documentElement.clientHeight; var width = document.documentElement.clientWidth; this.viewStyle.height = height; this.viewStyle.width = width; this.canvas = document.getElementById(this.id); this.canvas.width = width; this.canvas.height = height; this.ctx = this.canvas.getContext('2d'); } saveData() { this.tools.push(this.tool); } newGraph() { this.setTool(); this.tool.startPoint = { ...this.mouse.down }; this.saveData(); } update() { this.clear(); this.draw(); } draw() { this.tools.forEach(d => { d.drawGraph() }) } clear() { this.ctx.clearRect(0, 0, this.viewStyle.width, this.viewStyle.height); } bindEvent() { this.onEvent(); } createImgData() { // this.canvas.toDataURL('image/jpeg', 0.99); this.canvas.toBlob(function (blob) { var link = document.getElementById('downMyCavans'); if (!link) { link = document.createElement('a'); document.body.appendChild(link); } var url = URL.createObjectURL(blob); link.href = url; link.download = Math.floor(Math.random() * 10000000) + "Download.jpg"; link.click(); URL.revokeObjectURL(url); }, 'image/jpeg', 0.99); } selTool(toolName) { this.toolName = toolName; } setTool() { switch (this.toolName) { case 'line': this.tool = new lineTool(this.ctx); break; case 'rect': this.tool = new rectTool(this.ctx); break; case 'circle': this.tool = new circleTool(this.ctx); break; case 'ellipse': this.tool = new ellipseTool(this.ctx); break; case 'cloud': this.tool = new cloudTool(this.ctx); break; case 'polygon': this.tool = new polygonTool(this.ctx); break; default: break; } } onEvent() { this.canvas.onmousedown = (e) => { this.mouseDown(e); } this.canvas.onmouseup = (e) => { this.mouseUp(e); } this.canvas.onmousemove = (e) => { this.mouseMove(e); } this.canvas.ondblclick = (e) => { this.dblClick(e); } } offEvent() { this.canvas.onmousedown = null; this.canvas.onmouseup = null; this.canvas.onmousemove = null; } mouseDown(e) { this.mouse.isMove = true; let x = e.x, y = e.y; let point = { x: x, y: y }; this.mouse.down = { x: x, y: y }; if (['cloud', 'polygon'].indexOf(this.toolName) >= 0) { if (this.tool && !this.tool.isCloseGraph) { this.tool.points.push({ ...this.mouse.down }); return true; } } this.newGraph(); } mouseMove(e) { if (this.mouse.isMove) { let x = e.x, y = e.y; let point = { x: x, y: y }; this.mouse.move = { x: x, y: y }; this.tool.endPoint = { ...this.mouse.move } this.update(); } } mouseUp(e) { if (['cloud', 'polygon'].indexOf(this.toolName) >= 0) { let x = e.x, y = e.y; let point = { x: x, y: y }; this.mouse.up = { x: x, y: y }; } else { this.mouse.isMove = false; } } clearMouse() { this.mouse = { down: { x: null, y: null }, move: { x: null, y: null }, up: { x: null, y: null }, isMove: false } } dblClick(e) { if (['cloud', 'polygon'].indexOf(this.toolName) >= 0) { //结束 let point = { ...this.tool.startPoint } const { x, y } = point; if (this.tool) { this.tool.isCloseGraph = true; this.tool.endPoint = { x, y }; } this.clearMouse(); this.update(); } } } let canvas = new Print('myCanvas'); function selToolClick(toolName) { canvas.selTool(toolName); } function exportImgData() { canvas.createImgData() } </script> </body> </html>