html5 canvas繪圖-多邊形的對象


html5的canvas是一種立即模式繪圖系統。當想canvas之中繪制內容時,瀏覽器立刻就會將這些內容畫到canvas之中,然后立刻忘掉剛才所畫的東西。如果要實現的是一個繪畫應用程序的話,那么立即模式繪圖系統就很合適,不過,如果要實現的是那種可以讓用戶創建並操作繪圖對象的畫圖應用程序,那么最好還是講可以編輯並繪制的那些圖形對象保存到一份列表中。

                                                程序清單,使用多邊形對象來實現畫圖應用程序

html代碼:

 1 <html>
 2   <head>
 3     <title>Polygon Objects</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: crosshair;
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 
26     </style>
27   </head>
28 
29    <body>
30       <canvas id='canvas' width='850' height='600'>
31          Canvas not supported
32       </canvas>
33 
34      <div id='controls'>
35        Stroke color: <select id='strokeStyleSelect'>
36                         <option value='red'>red</option>
37                         <option value='green'>green</option>
38                         <option value='blue'>blue</option>
39                         <option value='orange'>orange</option>
40                         <option value='cornflowerblue' selected>cornflowerblue</option>
41                         <option value='goldenrod'>goldenrod</option>
42                         <option value='navy'>navy</option>
43                         <option value='purple'>purple</option>
44                      </select>
45 
46        Fill color: <select id='fillStyleSelect'>
47                         <option value='rgba(255,0,0,0.5)'>semi-transparent red</option>
48                         <option value='green'>green</option>
49                         <option value='rgba(0,0,255,0.5)'>semi-transparent blue</option>
50                         <option value='orange'>orange</option>
51                         <option value='rgba(100,140,230,0.5)'>semi-transparent cornflowerblue</option>
52                         <option value='goldenrod' selected>goldenrod</option>
53                         <option value='navy'>navy</option>
54                         <option value='purple'>purple</option>
55                      </select>
56 
57        Sides: <select id='sidesSelect'>
58                         <option value=4 select>4</option>
59                         <option value=6>6</option>
60                         <option value=8>8</option>
61                         <option value=10>10</option>
62                         <option value=12>12</option>
63                         <option value=20>20</option>
64                      </select>
65 
66        
67        Start angle: <select id='startAngleSelect'>
68                         <option value=0 select>0</option>
69                         <option value=22.5>22.5</option>
70                         <option value=45>45</option>
71                         <option value=67.5>67.5</option>
72                         <option value=90>90</option>
73                      </select>
74 
75        Fill <input id='fillCheckbox' type='checkbox' checked/>
76        <input id='eraseAllButton' type='button' value='Erase all'/>
77     </div>
78 
79     <script src = '../../shared/js/polygon.js'></script>
80     <script src = 'example.js'></script>
81   </body>
82 </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 
 17     dragging = false,
 18     draggingOffsetX,
 19     draggingOffsetY,
 20 
 21     sides = 8,
 22     startAngle = 0,
 23 
 24     guidewires = true,
 25 
 26     polygons = [],
 27     tmpPolygon = new Polygon(0,0,1,4,0,'blue','red',false),
 28 
 29     Point = function (x, y) {
 30        this.x = x;
 31        this.y = y;
 32     };
 33 
 34 
 35 // Functions.....................................................
 36 
 37 function drawGrid(color, stepx, stepy) {
 38    context.save()
 39 
 40    context.shadowColor = undefined;
 41    context.shadowOffsetX = 0;
 42    context.shadowOffsetY = 0;
 43    
 44    context.strokeStyle = color;
 45    context.fillStyle = '#ffffff';
 46    context.lineWidth = 0.5;
 47    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
 48 
 49    for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
 50      context.beginPath();
 51      context.moveTo(i, 0);
 52      context.lineTo(i, context.canvas.height);
 53      context.stroke();
 54    }
 55 
 56    for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
 57      context.beginPath();
 58      context.moveTo(0, i);
 59      context.lineTo(context.canvas.width, i);
 60      context.stroke();
 61    }
 62 
 63    context.restore();
 64 }
 65 
 66 function windowToCanvas(x, y) {
 67    var bbox = canvas.getBoundingClientRect();
 68    return { x: x - bbox.left * (canvas.width  / bbox.width),
 69             y: y - bbox.top  * (canvas.height / bbox.height)
 70           };
 71 }
 72 
 73 // Save and restore drawing surface..............................
 74 
 75 function saveDrawingSurface() {
 76    drawingSurfaceImageData = context.getImageData(0, 0,
 77                              canvas.width,
 78                              canvas.height);
 79 }
 80 
 81 function restoreDrawingSurface() {
 82    context.putImageData(drawingSurfaceImageData, 0, 0);
 83 }
 84 
 85 // Rubberbands...................................................
 86 
 87 function updateRubberbandRectangle(loc) {
 88    rubberbandRect.width = Math.abs(loc.x - mousedown.x);
 89    rubberbandRect.height = Math.abs(loc.y - mousedown.y);
 90 
 91    if (loc.x > mousedown.x) rubberbandRect.left = mousedown.x;
 92    else                     rubberbandRect.left = loc.x;
 93 
 94    if (loc.y > mousedown.y) rubberbandRect.top = mousedown.y;
 95    else                     rubberbandRect.top = loc.y;
 96 } 
 97 
 98 function drawRubberbandShape(loc, sides, startAngle) {
 99    var polygon = new Polygon(mousedown.x, mousedown.y,
100                      rubberbandRect.width, 
101                      parseInt(sidesSelect.value),
102                      (Math.PI / 180) * parseInt(startAngleSelect.value),
103                      context.strokeStyle,
104                      context.fillStyle,
105                      fillCheckbox.checked);
106 
107    context.beginPath();
108    polygon.createPath(context);
109    polygon.stroke(context);
110 
111    if (fillCheckbox.checked) {
112       polygon.fill(context);
113    }
114 
115    if (!dragging) {
116       polygons.push(polygon);
117    }
118 }
119 
120 function updateRubberband(loc, sides, startAngle) {
121    updateRubberbandRectangle(loc);
122    drawRubberbandShape(loc, sides, startAngle);
123 }
124 
125 // Guidewires....................................................
126 
127 function drawHorizontalLine (y) {
128    context.beginPath();
129    context.moveTo(0,y+0.5);
130    context.lineTo(context.canvas.width,y+0.5);
131    context.stroke();
132 }
133 
134 function drawVerticalLine (x) {
135    context.beginPath();
136    context.moveTo(x+0.5,0);
137    context.lineTo(x+0.5,context.canvas.height);
138    context.stroke();
139 }
140 
141 function drawGuidewires(x, y) {
142    context.save();
143    context.strokeStyle = 'rgba(0,0,230,0.4)';
144    context.lineWidth = 0.5;
145    drawVerticalLine(x);
146    drawHorizontalLine(y);
147    context.restore();
148 }
149 
150 function drawPolygons() {
151    polygons.forEach( function (polygon) {
152       polygon.stroke(context);
153       if (polygon.filled) {
154          polygon.fill(context);
155       }
156    });
157 }
158 
159 function startDragging(loc) {
160   saveDrawingSurface();
161   mousedown.x = loc.x;
162   mousedown.y = loc.y;
163 }
164 
165 // Event handlers................................................
166 
167 canvas.onmousedown = function (e) {
168    var loc = windowToCanvas(e.clientX, e.clientY);
169 
170    e.preventDefault(); // prevent cursor change
171 
172    startDragging(loc);
173    dragging = true;
174 };
175 
176 canvas.onmousemove = function (e) {
177    var loc = windowToCanvas(e.clientX, e.clientYe);
178 
179    e.preventDefault(); // prevent selections
180 
181   if (dragging) {
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.clientX, e.clientY);
193 
194    dragging = false;
195    restoreDrawingSurface();
196    updateRubberband(loc);
197 };
198 
199 eraseAllButton.onclick = function (e) {
200    context.clearRect(0, 0, canvas.width, canvas.height);
201    drawGrid('lightgray', 10, 10);
202    saveDrawingSurface(); 
203 };
204 
205 strokeStyleSelect.onchange = function (e) {
206    context.strokeStyle = strokeStyleSelect.value;
207 };
208 
209 fillStyleSelect.onchange = function (e) {
210    context.fillStyle = fillStyleSelect.value;
211 };
212 
213 // Initialization................................................
214 
215 context.strokeStyle = strokeStyleSelect.value;
216 context.fillStyle = fillStyleSelect.value;
217 
218 context.shadowOffsetX = 2;
219 context.shadowOffsetY = 2;
220 context.shadowBlur = 4;
221 
222 drawGrid('lightgray', 10, 10);

應用程序在用戶按下並拖動鼠標時,會調用drawRubberbandshape函數,以創建多邊形。此函數先創建一個表示多邊形的對象,然后調用該對象的createPath()方法,最后對創建出的路徑進行描邊,必要時還會填充。

如果用戶在拖動之后將鼠標松開,那么drawRubberbandShape()函數就會將當前這個多邊形加入到應用程序所維護的那份多邊形對象列表之中。

本小節中所實現的多邊形對象包含下列方法:

points[] getPoints()

void createPath(context)

void stroke(context)

void fill(context)

void move(x,y)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM