View Post


html5 canvas绘图-多边形的绘制

现在,我们已经将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代码:

  1 var canvas = document.getElementById(\'canvas\'),
  2     context = canvas.getContext(\'2d\'),
  3     eraseAllButton = document.getElementById(\'eraseAllButton\'),
  4     strokeStyleSelect = document.getElementById(\'strokeStyleSelect\'),
  5     startAngleSelect = document.getElementById(\'startAngleSelect\'),
  6 
  7     fillStyleSelect = document.getElementById(\'fillStyleSelect\'),
  8     fillCheckbox = document.getElementById(\'fillCheckbox\'),
  9 
 10     sidesSelect = document.getElementById(\'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) {
 24        this.x = x;
 25        this.y = y;
 26     };
 27 
 28 
 29 // Functions.....................................................
 30 
 31 function 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 
 39    for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
 40      context.beginPath();
 41      context.moveTo(i, 0);
 42      context.lineTo(i, context.canvas.height);
 43      context.stroke();
 44    }
 45 
 46    for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
 47      context.beginPath();
 48      context.moveTo(0, i);
 49      context.lineTo(context.canvas.width, i);
 50      context.stroke();
 51    }
 52 
 53    context.restore();
 54 }
 55 
 56 function windowToCanvas(e) {
 57    var x = e.x || e.clientX,
 58        y = e.y || e.clientY,
 59        bbox = canvas.getBoundingClientRect();
 60 
 61    return { x: x - bbox.left * (canvas.width  / bbox.width),
 62             y: y - bbox.top  * (canvas.height / bbox.height)
 63           };
 64 }
 65 
 66 // Save and restore drawing surface..............................
 67 
 68 function saveDrawingSurface() {
 69    drawingSurfaceImageData = context.getImageData(0, 0,
 70                              canvas.width,
 71                              canvas.height);
 72 }
 73 
 74 function restoreDrawingSurface() {
 75    context.putImageData(drawingSurfaceImageData, 0, 0);
 76 }
 77 
 78 // Rubberbands...................................................
 79 
 80 function updateRubberbandRectangle(loc) {
 81    rubberbandRect.width = Math.abs(loc.x - mousedown.x);
 82    rubberbandRect.height = Math.abs(loc.y - mousedown.y);
 83 
 84    if (loc.x > mousedown.x) rubberbandRect.left = mousedown.x;
 85    else                     rubberbandRect.left = loc.x;
 86 
 87    if (loc.y > mousedown.y) rubberbandRect.top = mousedown.y;
 88    else                     rubberbandRect.top = loc.y;
 89 } 
 90 
 91 function getPolygonPoints(centerX, centerY, radius, sides, startAngle) {
 92    var points = [],
 93        angle = startAngle || 0;
 94 
 95    for (var i=0; i < sides; ++i) {
 96       points.push(new Point(centerX + radius * Math.sin(angle),
 97                         centerY - radius * Math.cos(angle)));
 98       angle += 2*Math.PI/sides;
 99    }
100 
101    return points;
102 }
103 
104 function createPolygonPath(centerX, centerY, radius, sides, startAngle) {
105    var points = getPolygonPoints(centerX, centerY, radius, sides, startAngle);
106 
107    context.beginPath();
108 
109    context.moveTo(points[0].x, points[0].y);
110 
111    for (var i=1; i < sides; ++i) {
112       context.lineTo(points[i].x, points[i].y);
113    }
114 
115    context.closePath();
116 }
117 
118 function 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 
125    if (fillCheckbox.checked) {
126       context.fill();
127    }
128 }
129 
130 function updateRubberband(loc, sides, startAngle) {
131    updateRubberbandRectangle(loc);
132    drawRubberbandShape(loc, sides, startAngle);
133 }
134 
135 // Guidewires....................................................
136 
137 function drawHorizontalLine (y) {
138    context.beginPath();
139    context.moveTo(0,y+0.5);
140    context.lineTo(context.canvas.width,y+0.5);
141    context.stroke();
142 }
143 
144 function drawVerticalLine (x) {
145    context.beginPath();
146    context.moveTo(x+0.5,0);
147    context.lineTo(x+0.5,context.canvas.height);
148    context.stroke();
149 }
150 
151 function 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    context.restore();
158 }
159 
160 // Event handlers................................................
161 
162 canvas.onmousedown = function (e) {
163    var 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 
175 canvas.onmousemove = function (e) {
176    var loc;
177 
178    if (dragging) {
179       e.preventDefault(); // prevent selections
180 
181       loc = windowToCanvas(e);
182       restoreDrawingSurface();
183       updateRubberband(loc, sides, startAngle);
184 
185       if (guidewires) {
186          drawGuidewires(mousedown.x, mousedown.y);
187       }
188    }
189 };
190 
191 canvas.onmouseup = function (e) {
192    var loc = windowToCanvas(e);
193    dragging = false;
194    restoreDrawingSurface();
195    updateRubberband(loc);
196 };
197 
198 eraseAllButton.onclick = function (e) {
199    context.clearRect(0, 0, canvas.width, canvas.height);
200    drawGrid(\'lightgray\', 10, 10);
201    saveDrawingSurface(); 
202 };
203 
204 strokeStyleSelect.onchange = function (e) {
205    context.strokeStyle = strokeStyleSelect.value;
206 };
207 
208 fillStyleSelect.onchange = function (e) {
209    context.fillStyle = fillStyleSelect.value;
210 };
211 
212 // Initialization................................................
213 
214 context.strokeStyle = strokeStyleSelect.value;
215 context.fillStyle = fillStyleSelect.value;
216 drawGrid(\'lightgray\', 10, 10);

上述程序清单中的代码首先获取了指向canvas绘图环境对象的引用,并且定义了一个名为point的对象。

getPolygonPoints()函数创建并返回了一个含有多边形顶点的数组,这个多边形是由该函数的5个参数所确定的。该函数运用图所写的算式来计算各个顶点的坐标,并创建了一个包含这些顶点的数组。

createPolygonPath()函数调用getPolygonPoints()函数,以获取包含指定多边形各个顶点的数组。该函数先移动到第一个顶点,然后创建一条包含此多边形所有顶点的路径。

最后,应用程序调用drawRubberbandShape()函数来完成多边形的绘制,这个函数是由上次中的那个drawRubberbandShape()函数改编而来的。

版权声明:本文为zxmeigood原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zxmeigood/p/3727195.html