4.canvas實現多邊形橡皮筋式繪圖功能
阿新 • • 發佈:2019-01-31
首先是html程式碼:
<div id="control"> Stroke color: <select id="strokeStyleSelect"> <option value="red">red</option> <option value="green">green</option> <option value="blue">blue</option> <option value="orange">orange</option> <option value="cornflowerblue">cornflowerblue</option> <option value="goldenrod">goldenrod</option> <option value="navy">navy</option> <option value="purple"selected>purple</option> </select> fill color: <select id="fillStyleSelect"> <option value="rgba(255,0,0,0.5)">red</option> <option value="rgba(0,255,0,0.5)">green</option> <option value="rgba(0,0,255,0.5)">blue</option> <option value="rgba(255,165,0,0.5)"selected>orange</option> <option value="rgba(100,149,237,0.5)">cornflowerblue</option> <option value="rgba(218,165,32,0.5)">goldenrod</option> <option value="rgba(0,0,128,0.5)">navy</option> <option value="rgba(160,32,240,0.5)">purple</option> <option value="rgba(0,0,0,0.5)">black</option> </select> sides: <select id="sidesSelect"> <option value="3"selected>3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> </select> start angle: <select id="startAngleSelect"> <option value="0" selected>0</option> <option value="15">15</option> <option value="30">30</option> <option value="45">45</option> <option value="60">60</option> <option value="75">75</option> <option value="90">90</option> <option value="0">105</option> <option value="15">120</option> <option value="30">135</option> <option value="45">150</option> <option value="60">165</option> <option value="75">180</option> </select> Fill: <input id="fillCheckbox" type="checkbox" checked/> Edit: <input id="editCheckbox" type="checkbox"/> <input id="eraseAllButton" type="button" value="erase all"/> </div> <canvas id='canvas'width=1200 height=650> can't use canvas </canvas>
js實現程式碼:
var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), eraseAllButton = document.getElementById('eraseAllButton'), strokeStyleSelect = document.getElementById('strokeStyleSelect'), fillStyleSelect = document.getElementById('fillStyleSelect'), fillcheckbox = document.getElementById('fillCheckbox'), editcheckbox = document.getElementById('editCheckbox'), drawingSurfaceImageData, mousedown = {}, rubberbandRect = {}, dragging = false, draggingOffsetX, draggingOffsetY, sidesSelect = document.getElementById('sidesSelect'), startAngleSelect = document.getElementById('startAngleSelect'), returnToLast = document.getElementById('returnToLast'), sides = 3, startAngle = 0, guidewire = true, editing =false, polygons = [], Point = function(x, y){ this.x = x; this.y = y; }; var Polygon = function(centerX, centerY, radius, sides,startAngle, strokeStyle, fillStyle, filled){ this.x = centerX; this.y = centerY; this.radius = radius; this.sides = sides; this.startAngle = startAngle; this.strokeStyle = strokeStyle; this.fillStyle = fillStyle; this.filled = filled; } Polygon.prototype = { getPoints: function(){ var points = [], angle = this.startAngle|| 0; for(var i = 0; i < this.sides; i++){ points.push(new Point(this.x+ this.radius* Math.sin(angle), this.y- this.radius* Math.cos(angle))); angle+= 2* Math.PI/ this.sides; } return points; }, createPath: function(context){ var points= this.getPoints(); context.beginPath(); context.moveTo(points[0].x, points[0].y); for(var i= 1; i< this.sides; i++){ context.lineTo(points[i].x, points[i].y); } context.closePath(); }, stroke: function(context){ context.save(); this.createPath(context); context.strokeStyle= this.strokeStyle; context.stroke(); context.restore(); }, fill: function(context){ context.save(); this.createPath(context); context.fillStyle= this.fillStyle; context.fill(); context.restore(); }, move: function(x, y){ this.x= x; this.y= y; } }; function windowToCanvas(x, y){ var bbox = canvas.getBoundingClientRect(); return {x: x - bbox.left * (canvas.width / bbox.width), y: y - bbox.top * (canvas.height / bbox.height)}; } function saveDrawingSurface(){ drawingSurfaceImageData = context.getImageData(0, 0, canvas.width, canvas.height); } function restoreDrawingface(){ context.putImageData(drawingSurfaceImageData, 0, 0); } function drawPolygon(polygon){ context.beginPath(); polygon.createPath(context); polygon.stroke(context); if(fillcheckbox.checked){ polygon.fill(context); } } function updateRubberbandRectangle(loc){ rubberbandRect.width= Math.abs(loc.x- mousedown.x); rubberbandRect.height= Math.abs(loc.y- mousedown.y); if(loc.x> mousedown.x) rubberbandRect.left= mousedown.x; else rubberbandRect.left= loc.x; if(loc.y> mousedown.y) rubberbandRect.top= mousedown.y; else rubberbandRect.top= loc.y; } function drawRubberbandShape(loc, sides, startAngle){ var polygon= new Polygon(mousedown.x, mousedown.y, rubberbandRect.width, parseInt(sidesSelect.value), (Math.PI/ 180)* parseInt(startAngleSelect.value), context.strokeStyle, context.fillStyle, fillcheckbox.checked); drawPolygon(polygon); if(!dragging) polygons.push(polygon); } function updateRubberband(loc, sides, startAngle){ updateRubberbandRectangle(loc); drawRubberbandShape(loc, sides, startAngle); } function drawPolygons(){ polygons.forEach(function(polygon){ drawPolygon(polygon); }); } function startDragging(loc){ saveDrawingSurface(); mousedown.x= loc.x; mousedown.y= loc.y; } function stopEditing(){ canvas.style.cursor= 'crosshair'; editing= false; } function startEditing(){ canvas.style.cursor= 'pointer'; editing= true; } canvas.onmousedown= function (e){ var loc= windowToCanvas(e.clientX, e.clientY); e.preventDefault(); if(editing){ polygons.forEach(function(polygon){ polygon.createPath(context); if(context.isPointInPath(loc.x, loc.y)){ startDragging(loc); dragging= polygon; draggingOffsetX= loc.x- polygon.x; draggingOffsetY= loc.y- polygon.y; return; } }); } else{ startDragging(loc); dragging= true; } }; canvas.onmousemove= function(e){ var loc= windowToCanvas(e.clientX, e.clientY); e.preventDefault(); if(editing && dragging){ dragging.x= loc.x - draggingOffsetX; dragging.y= loc.y - draggingOffsetY; context.clearRect(0, 0, canvas.width, canvas.height); drawPolygons(); } else{ if(dragging){ restoreDrawingface(); updateRubberband(loc, sides, startAngle); } } }; canvas.onmouseup= function(e){ var loc= windowToCanvas(e.clientX, e.clientY); dragging= false; if(editing){ } else{ restoreDrawingface(); updateRubberband(loc); } }; eraseAllButton.onclick= function(e){ context.clearRect(0, 0, canvas.width, canvas.height); polygons= []; saveDrawingSurface(); }; strokeStyleSelect.onchange=function(e){ context.strokeStyle= strokeStyleSelect.value; }; fillStyleSelect.onchange = function(e){ context.fillStyle = fillStyleSelect.value; }; editcheckbox.onchange = function(e){ if(editcheckbox.checked){ startEditing(); } else stopEditing(); }; context.lineWidth= 20; context.strokeStyle = strokeStyleSelect.value; context.fillStyle = fillStyleSelect.value;