html5canvas绘图-多边形的绘制
现在,我们已经将CANVAS绘图环境对象所⽀持的全部基本图形都讲完了。它们包括:线段、矩形、圆弧、圆形以及贝塞尔曲线。但是,我们肯定需要在canvas之中绘制除此之外的其他图形,⽐⽅说,三⾓形、六边形和⼋边形。在本节中,你将会学到如下图所⽰的应⽤程序,对任意对变形进⾏描边及填充。
使⽤moveTo()与lineTo()⽅法,再结合⼀些简单的三⾓函数,就可以绘制出任意边数的多边形。
html代码:
1<html>
2<head>
3<title>Drawing Polygons</title>
4
5<style>
6      body {
7        background: #eeeeee;
8      }
9
10      #controls {
11        position: absolute;
12        left: 25px;
13        top: 25px;
14      }
15
16      #canvas {
17        background: #ffffff;
18        cursor: pointer;
19        margin-left: 10px;
20        margin-top: 10px;
21        -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
22        -moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
23        box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
24      }
25</style>
26</head>
27
28<body>
29<canvas id='canvas' width='850' height='600'>
30          Canvas not supported
31</canvas>
32
33<div id='controls'>
34        Stroke color: <select id='strokeStyleSelect'>
35<option value='red'>red</option>
36<option value='green'>green</option>
37<option value='blue'>blue</option>
38<option value='orange'>orange</option>
39<option value='cornflowerblue' selected>cornflowerblue</option>
40<option value='goldenrod'>goldenrod</option>
41<option value='navy'>navy</option>
42<option value='purple'>purple</option>
43</select>
44
45        Fill color: <select id='fillStyleSelect'>
46<option value='rgba(255,0,0,0.5)'>semi-transparent red</option>
47<option value='green'>green</option>
48<option value='rgba(0,0,255,0.5)'>semi-transparent blue</option>
49<option value='orange'>orange</option>
50<option value='rgba(100,140,230,0.5)'>semi-transparent cornflowerblue</option>
51<option value='goldenrod' selected>goldenrod</option>
52<option value='navy'>navy</option>
53<option value='purple'>purple</option>
54</select>
55
56        Sides: <select id='sidesSelect'>
57<option value=4 select>4</option>
58<option value=6>6</option>
59<option value=8>8</option>
60<option value=10>10</option>
61<option value=12>12</option>
62<option value=20>20</option>
63</select>
64
65        Start angle: <select id='startAngleSelect'>
66<option value=0 select>0</option>
67<option value=22.5>22.5</option>
68<option value=45>45</option>
69<option value=67.5>67.5</option>
70<option value=90>90</option>
71</select>
72
73        Fill <input id='fillCheckbox' type='checkbox' checked/>
74<input id='eraseAllButton' type='button' value='Erase all'/>
75</div>
76
77<script src = 'example.js'></script>
78</body>
79</html>
example.js代码:
1var canvas = ElementById('canvas'),
2    context = Context('2d'),
3    eraseAllButton = ElementById('eraseAllButton'),
4    strokeStyleSelect = ElementById('strokeStyleSelect'),
5    startAngleSelect = ElementById('startAngleSelect'),  6
7    fillStyleSelect = ElementById('fillStyleSelect'),
8    fillCheckbox = ElementById('fillCheckbox'),
9
10    sidesSelect = ElementById('sidesSelect'),
11
12    drawingSurfaceImageData,
13
14    mousedown = {},
15    rubberbandRect = {},
16    dragging = false,
17
18    sides = 8,
19    startAngle = 0,
20
21    guidewires = true,
22
23    Point = function (x, y) {
24this.x = x;
25this.y = y;
26    };
27
28
29//
30
31function drawGrid(color, stepx, stepy) {
32    context.save()
33
34    context.strokeStyle = color;
35    context.fillStyle = '#ffffff';
36    context.lineWidth = 0.5;
37    context.fillRect(0, 0, context.canvas.width, context.canvas.height); 38
39for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
40      context.beginPath();
41      veTo(i, 0);
42      context.lineTo(i, context.canvas.height);
43      context.stroke();
44    }
45
46for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
47      context.beginPath();
48      veTo(0, i);
49      context.lineTo(context.canvas.width, i);
50      context.stroke();
51    }
52
53    store();
54 }
55
56function windowToCanvas(e) {
57var x = e.x || e.clientX,
58        y = e.y || e.clientY,
59        bbox = BoundingClientRect();
60
61return { x: x - bbox.left * (canvas.width  / bbox.width),
62            y: y - p  * (canvas.height / bbox.height)
63          };
64 }
65
66// Save and restore .
67
68function saveDrawingSurface() {
69    drawingSurfaceImageData = ImageData(0, 0,
70                              canvas.width,
71                              canvas.height);
72 }
73
74function restoreDrawingSurface() {
75    context.putImageData(drawingSurfaceImageData, 0, 0);
76 }
77
78// .
79
80function updateRubberbandRectangle(loc) {
81    rubberbandRect.width = Math.abs(loc.x - mousedown.x);
82    rubberbandRect.height = Math.abs(loc.y - mousedown.y);
83
84if (loc.x > mousedown.x) rubberbandRect.left = mousedown.x;
85else                    rubberbandRect.left = loc.x;
86
87if (loc.y > mousedown.y) p = mousedown.y;
88else                    p = loc.y;
89 }
90
91function getPolygonPoints(centerX, centerY, radius, sides, startAngle) {
92var points = [],
93        angle = startAngle || 0;
94
95for (var i=0; i < sides; ++i) {
96      points.push(new Point(centerX + radius * Math.sin(angle),
97                        centerY - radius * s(angle)));
98      angle += 2*Math.PI/sides;
99    }
100
101return points;
102 }
103
104function createPolygonPath(centerX, centerY, radius, sides, startAngle) { 105var points = getPolygonPoints(centerX, centerY, radius, sides, startAngle); 106
107    context.beginPath();
108
109    veTo(points[0].x, points[0].y);
110
111for (var i=1; i < sides; ++i) {
112      context.lineTo(points[i].x, points[i].y);
113    }
114
115    context.closePath();
116 }
117
118function drawRubberbandShape(loc, sides, startAngle) {
119    createPolygonPath(mousedown.x, mousedown.y,
120                      rubberbandRect.width,
121                      parseInt(sidesSelect.value),
122                      (Math.PI / 180) * parseInt(startAngleSelect.value));
123    context.stroke();
124
125if (fillCheckbox.checked) {
126      context.fill();
127    }
128 }
129
130function updateRubberband(loc, sides, startAngle) {
131    updateRubberbandRectangle(loc);
132    drawRubberbandShape(loc, sides, startAngle);
133 }
134
135//
136
137function drawHorizontalLine (y) {
138    context.beginPath();
139    veTo(0,y+0.5);
140    context.lineTo(context.canvas.width,y+0.5);
141    context.stroke();
142 }
143
144function drawVerticalLine (x) {
145    context.beginPath();
146    veTo(x+0.5,0);
147    context.lineTo(x+0.5,context.canvas.height);
148    context.stroke();
149 }
150
151function drawGuidewires(x, y) {
152    context.save();
153    context.strokeStyle = 'rgba(0,0,230,0.4)';
154    context.lineWidth = 0.5;
155    drawVerticalLine(x);
156    drawHorizontalLine(y);
157    store();
158 }
159
160//
161
usedown = function (e) {
163var loc = windowToCanvas(e);
164
165    saveDrawingSurface();
166
167    e.preventDefault(); // prevent cursor change
168
169    saveDrawingSurface();
170    mousedown.x = loc.x;
171    mousedown.y = loc.y;
172    dragging = true;
173 };
174
usemove = function (e) {
176var loc;
177
178if (dragging) {
179      e.preventDefault(); // prevent selections
180
181      loc = windowToCanvas(e);
182      restoreDrawingSurface();
183      updateRubberband(loc, sides, startAngle);
184
185if (guidewires) {
186          drawGuidewires(mousedown.x, mousedown.y);
187      }
188    }html矩形框代码怎么写
189 };
190
useup = function (e) {
192var loc = windowToCanvas(e);
193    dragging = false;
194    restoreDrawingSurface();
195    updateRubberband(loc);
196 };
197
lick = function (e) {
199    context.clearRect(0, 0, canvas.width, canvas.height);
200    drawGrid('lightgray', 10, 10);
201    saveDrawingSurface();
202 };
203
hange = function (e) {
205    context.strokeStyle = strokeStyleSelect.value;
206 };
207
hange = function (e) {
209    context.fillStyle = fillStyleSelect.value;
210 };
211
212//
213
214 context.strokeStyle = strokeStyleSelect.value;
215 context.fillStyle = fillStyleSelect.value;
216 drawGrid('lightgray', 10, 10);
上述程序清单中的代码⾸先获取了指向canvas绘图环境对象的引⽤,并且定义了⼀个名为point的对象。
getPolygonPoints()函数创建并返回了⼀个含有多边形顶点的数组,这个多边形是由该函数的5个参数所确定的。该函数运⽤图所写的算式来计算各个顶点的坐标,并创建了⼀个包含这些顶点的数组。
createPolygonPath()函数调⽤getPolygonPoints()函数,以获取包含指定多边形各个顶点的数组。该函数先移动到第⼀个顶点,然后创建⼀条包含此多边形所有顶点的路径。
最后,应⽤程序调⽤drawRubberbandShape()函数来完成多边形的绘制,这个函数是由上次中的那个drawRubberbandShape()函数改编⽽来的。