关于canvas的save()和restore(),前面一直以为canvas的画面也会保存,然后restore后把画面恢复,那么就这样把自己给绕进去了,那么save和restore之间的操作还有何意义???
摸爬滚打后理解了save 保存的是画布的坐标旋转缩放 以及fillstyle 和 其他等等的相关属性,已经画好了的图画不在之列。
做了个菊花 和 前面做的图片旋转移动 的 demo 来巩固下。
依然先看效果
---------------------代码分割线-----------------------------------------------------------------------------------------
1 var $=function(id){
2
3 return document.getElementById(id);
4
5 }
6
7 var isinit=false;
8
9 /** Canvas 类
10
11 *
12
13 * @param {Object} height
14
15 */
16
17 var g_loadings = [];
18
19 function Canvas(height, con){
20
21 if (height == null) {
22
23 height = 24;
24
25 }
26
27 this.obj = document.createElement("canvas");
28
29 var width = height;
30
31 if(con != null){
32
33 width += 82;
34
35 }
36
37 this.obj.setAttribute("width", width+500);
38
39 this.obj.setAttribute("height", height+500);
40
41 this.height = height;
42
43 this.ctx = this.obj.getContext("2d");
44
45 // RGB
46
47 this.color = [51, 51, 51];
48
49 var fsize = "14px";
50
51 if(height>24){
52
53 fsize = "16px";
54
55 }
56
57 this.ctx.save();
58
59 this.ctx.fillStyle = "#646464";
60
61 this.ctx.font = fsize+" \"Microsoft YaHei\",Helvetica";
62
63 this.ctx.textBaseline = "middle";
64
65 this.ctx.fillText(con, height+5, height/2);
66
67 this.ctx.restore();
68
69 }
70
71 // 记录转动的度数,分8步
72
73 Canvas.prototype.rotation = 0;
74
75 // 每隔125ms会调用一次,绘制一个loading圆
76
77 Canvas.prototype.draw = function(){
78
79 var h = this.height, ctx = this.ctx, c = h / 16, d = h / 5, degree = -Math.PI * 2 / 10;
80
81
82
83 //ctx.save();
84
85 // clearRect(x,y,width,height) : Clears the specified area and makes it fully transparent
86
87 ctx.clearRect(-200, -200, 500, 500);
88
89
90
91 // 移到中点
92
93 if (!isinit){
94
95 ctx.translate(h / 2, h / 2);
96
97 isinit=true;
98
99 }
100
101
102
103
104
105
106
107 // 把一个圆分成8段,分别绘制
108
109 for (var i = 0; i < 10; i++) {
110
111
112
113 ctx.save();
114
115 // 旋转一段的度数
116
117 ctx.rotate(i * degree);
118
119 // 根据旋转的角度设置颜色与透明度,eg:
120
121 // rotation=0 的时候, alpha的值 1, 0.875 ... 0.125
122
123 // rotation=1 的时候, alpha的值 0.875, 0.75 ... 1
124
125 ctx.fillStyle = "rgba(" + this.color[0] + "," + this.color[1] + "," + this.color[2] + "," + (10 - (i + this.rotation) % 10) / 10 + ")";
126
127 // 绘制 fillRect(x,y,width,height) : Draws a filled rectangle
128
129 ctx.fillRect(-c / 2, d, c, d);
130
131 ctx.restore();
132
133 }
134
135 //ctx.restore();
136
137
138
139 this.rotation++;
140
141 this.rotation %= 10;
142
143 var load_canvas=this;
144
145 load_canvas.running = window.setTimeout(function(){load_canvas.draw();load_canvas=null;}, 100); // 由于分成10段,所以时间为100ms
146
147 };
148
149
150
151 /**
152
153 * 创建Canvas
154
155 *
156
157 * @param {Object} parent 父节点,之前必须要至少一个子节点存在
158
159 * 如 <a ><span>取消</span></a>
160
161 * @param {Object} height 长/高
162
163 */
164
165 function initCanvas(parent, height, con){
166
167 // 如果是有子节点,说明需要做 loading 动画
168
169 if (parent && parent.firstChild && parent.firstChild.id != "sp") {
170
171 // 创建 Canvas
172
173 var canvas = new Canvas(height, con);
174
175 canvas.obj.id = "sp";
176
177 // 放进数组
178
179 g_loadings.push(canvas);
180
181 parent.insertBefore(canvas.obj, parent.firstChild);
182
183 if (!canvas.running) {
184
185
186
187 canvas.draw();
188
189 }
190
191 }
192
193 }
194
195
196
197 /**
198
199 * 删除 Canvas
200
201 * @param {Object} parent 父节点
202
203 * @param 返回 1 说明成功删除了一个正在loading状态的canvas
204
205 */
206
207 function removeCanvas(parent){
208
209 if (parent && parent.firstChild && parent.firstChild.id == "sp") {
210
211 // loop整个数组中的 canvas
212
213 for (var i = g_loadings.length; --i >= 0;) {
214
215 var canvas = g_loadings[i];
216
217 if (canvas.obj == parent.firstChild) {
218
219 //从 Dom 移除
220
221 parent.removeChild(parent.firstChild);
222
223 // remove interval
224
225 window.clearInterval(canvas.running);
226
227 canvas.running = null;
228
229 // 去掉
230
231 g_loadings.splice(i, 1);
232
233 return 1;
234
235 }
236
237 }
238
239 }
240
241 return 0;
242
243 }
244
245 function getOuterHeight(obj){
246
247 var mtop = obj.style.marginTop;
248
249 if(mtop==""){
250
251 mtop = 0;
252
253 }
254
255 var mbottom = obj.style.marginBottom;
256
257 if(mbottom==""){
258
259 mbottom = 0;
260
261 }
262
263 return obj.offsetHeight+parseInt(mtop)+parseInt(mbottom);
264
265 }
266
267 /**
268
269 * 页面统一 loading
270
271 * @param btnObj 如果有,则只给这个按钮加,否则整个页面
272
273 */
274
275 function loading(btnObj, height, con){
276
277
278
279 if(con == null){
280
281 con = "正在载入...";
282
283 }
284
285 if(btnObj){
286
287 if(height == null){
288
289 height = 24;
290
291 }
292
293 //给按钮加上loading
294
295 btnObj.setAttribute("selected", "progress");
296
297 btnObj.style.display = "block";
298
299 try{
300
301 initCanvas(btnObj, height, con);
302
303 }catch(ex){}
304
305 }else{
306
307 if(height == null){
308
309 height = 32;
310
311 }
312
313 //全局的
314
315 if(!$("preloader")){
316
317 var oDiv = document.createElement("div");
318
319 oDiv.id = "preloader";
320
321 oDiv.style.textAlign = "center";
322
323 //oDiv.style.position = "relative";
324
325 var oSpan = document.createElement("span");
326
327 oDiv.appendChild(oSpan);
328
329 document.getElementsByTagName("body")[0].appendChild(oDiv);
330
331 }
332
333 var overlay = $("preloader");
334
335 //var oHeight = getOuterHeight(overlay);
336
337 //定位到中间
338
339 //var top = parseInt(Math.max((getClientHeight() - oHeight) / 2, 0) + getScrollTop());
340
341 //overlay.style.top = (top-height)+"px";
342
343 overlay.style.marginTop = "150px";
344
345 overlay.style.display = "block";
346
347 try{
348
349 initCanvas(overlay, height, con);
350
351 }catch(ex){}
352
353 }
354
355 }
356
357
358
359 /**
360
361 * 停止页面统一loading
362
363 * @param btnObj 如果有,则只给这个按钮,否则整个页面
364
365 * @return 1/0 如果返回1说明已经有对应的实例在loading状态,此时要根据情况判断是否继续
366
367 */
368
369 function unloading(btnObj){
370
371 var result = 0;
372
373 if(btnObj){
374
375 //给按钮加上loading
376
377 result = removeCanvas(btnObj);
378
379 btnObj.removeAttribute("selected");
380
381 btnObj.style.display = "none";
382
383 return result;
384
385 }else{
386
387 //全局的
388
389 var overlay = $("preloader");
390
391 result = removeCanvas(overlay);
392
393 overlay.style.display = "none";
394
395 overlay.style.marginTop = "";
396
397 return result;
398
399 }
400
401 }
402
403
404
405 loading(null , 110 );