HTML5 Canvas笔记——Canvas绘制多边形
2020-04-26 本文已影响0人
没昔
Canvas绘制多边形
多边形绘制.html
<html>
<head>
<title>多边形绘制</title>
<style>
body {
background: #eeeeee;
}
#controls {
position: absolute;
left: 25px;
top: 25px;
}
#canvas {
background: #ffffff;
cursor: crosshair;
margin-left: 10px;
margin-top: 10px;
-webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
-moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<canvas id='canvas' width='1000' height='600'>
Canvas not supported
</canvas>
<div id='controls'>
颜色: <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' selected>cornflowerblue</option>
<option value='goldenrod'>goldenrod</option>
<option value='navy'>navy</option>
<option value='purple'>purple</option>
</select>
填充颜色: <select id='fillStyleSelect'>
<option value='rgba(255,0,0,0.5)'>semi-transparent red</option>
<option value='green'>green</option>
<option value='rgba(0,0,255,0.5)'>semi-transparent blue</option>
<option value='orange'>orange</option>
<option value='rgba(100,140,230,0.5)'>semi-transparent cornflowerblue</option>
<option value='goldenrod' selected>goldenrod</option>
<option value='navy'>navy</option>
<option value='purple'>purple</option>
</select>
几个角: <select id='sidesSelect'>
<option value=4 select>4</option>
<option value=6>6</option>
<option value=8>8</option>
<option value=10>10</option>
<option value=12>12</option>
<option value=20>20</option>
</select>
角度: <select id='startAngleSelect'>
<option value=0 select>0</option>
<option value=22.5>22.5</option>
<option value=45>45</option>
<option value=67.5>67.5</option>
<option value=90>90</option>
</select>
是否填充:
<input id='fillCheckbox' type='checkbox' checked/>
<input id='eraseAllButton' type='button' value='Erase all'/>
</div>
<script src = 'polygon.js'></script>
<script src = 'example.js'></script>
</body>
</html>
example.js
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
eraseAllButton = document.getElementById('eraseAllButton'),
strokeStyleSelect = document.getElementById('strokeStyleSelect'),
startAngleSelect = document.getElementById('startAngleSelect'),
fillStyleSelect = document.getElementById('fillStyleSelect'),
fillCheckbox = document.getElementById('fillCheckbox'),
sidesSelect = document.getElementById('sidesSelect'),
drawingSurfaceImageData,
mousedown = {},
rubberbandRect = {},
dragging = false,
draggingOffsetX,
draggingOffsetY,
sides = 8,
startAngle = 0,
guidewires = true,
polygons = [],
tmpPolygon = new Polygon(0,0,1,4,0,'blue','red',false),
Point = function (x, y) {
this.x = x;
this.y = y;
};
// Functions.....................................................
function drawGrid(color, stepx, stepy) {
context.save()
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.strokeStyle = color;
context.fillStyle = '#ffffff';
context.lineWidth = 0.5;
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
context.beginPath();
context.moveTo(i, 0);
context.lineTo(i, context.canvas.height);
context.stroke();
}
for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
}
context.restore();
}
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)
};
}
// Save and restore drawing surface..............................
function saveDrawingSurface() {
drawingSurfaceImageData = context.getImageData(0, 0,
canvas.width,
canvas.height);
}
function restoreDrawingSurface() {
context.putImageData(drawingSurfaceImageData, 0, 0);
}
// Rubberbands...................................................
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);
context.beginPath();
polygon.createPath(context);
polygon.stroke(context);
if (fillCheckbox.checked) {
polygon.fill(context);
}
if (!dragging) {
polygons.push(polygon);
}
}
function updateRubberband(loc, sides, startAngle) {
updateRubberbandRectangle(loc);
drawRubberbandShape(loc, sides, startAngle);
}
// Guidewires....................................................
function drawHorizontalLine (y) {
context.beginPath();
context.moveTo(0,y+0.5);
context.lineTo(context.canvas.width,y+0.5);
context.stroke();
}
function drawVerticalLine (x) {
context.beginPath();
context.moveTo(x+0.5,0);
context.lineTo(x+0.5,context.canvas.height);
context.stroke();
}
function drawGuidewires(x, y) {
context.save();
context.strokeStyle = 'rgba(0,0,230,0.4)';
context.lineWidth = 0.5;
drawVerticalLine(x);
drawHorizontalLine(y);
context.restore();
}
function drawPolygons() {
polygons.forEach( function (polygon) {
polygon.stroke(context);
if (polygon.filled) {
polygon.fill(context);
}
});
}
function startDragging(loc) {
saveDrawingSurface();
mousedown.x = loc.x;
mousedown.y = loc.y;
}
// Event handlers................................................
canvas.onmousedown = function (e) {
var loc = windowToCanvas(e.clientX, e.clientY);
e.preventDefault(); // prevent cursor change
startDragging(loc);
dragging = true;
};
canvas.onmousemove = function (e) {
var loc = windowToCanvas(e.clientX, e.clientYe);
e.preventDefault(); // prevent selections
if (dragging) {
restoreDrawingSurface();
updateRubberband(loc, sides, startAngle);
if (guidewires) {
drawGuidewires(mousedown.x, mousedown.y);
}
}
};
canvas.onmouseup = function (e) {
var loc = windowToCanvas(e.clientX, e.clientY);
dragging = false;
restoreDrawingSurface();
updateRubberband(loc);
};
eraseAllButton.onclick = function (e) {
context.clearRect(0, 0, canvas.width, canvas.height);
drawGrid('lightgray', 10, 10);
saveDrawingSurface();
};
strokeStyleSelect.onchange = function (e) {
context.strokeStyle = strokeStyleSelect.value;
};
fillStyleSelect.onchange = function (e) {
context.fillStyle = fillStyleSelect.value;
};
// Initialization................................................
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = fillStyleSelect.value;
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowBlur = 4;
drawGrid('lightgray', 10, 10);
polygon.js
var Point = function (x, y) {
this.x = x;
this.y = y;
};
var Polygon = function (centerX, centerY, radius, sides, startAngle, strokeStyle, fillStyle, filled) {
this.x = centerX;//外接圆心x坐标
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;
},
};