1 /**
  2  * Hilo
  3  * Copyright 2015 alibaba.com
  4  * Licensed under the MIT License
  5  */
  6 
  7 /**
  8  * @language=zh
  9  * @class canvas画布渲染器。所有可视对象将渲染在canvas画布上。舞台Stage会根据参数canvas选择不同的渲染器,开发者无需直接使用此类。
 10  * @augments Renderer
 11  * @param {Object} properties 创建对象的属性参数。可包含此类所有可写属性。
 12  * @module hilo/renderer/CanvasRenderer
 13  * @requires hilo/core/Class
 14  * @requires hilo/core/Hilo
 15  * @requires hilo/renderer/Renderer
 16  * @property {CanvasRenderingContext2D} context canvas画布的上下文。只读属性。
 17  */
 18 var CanvasRenderer = Class.create(/** @lends CanvasRenderer.prototype */{
 19     Extends: Renderer,
 20     constructor: function(properties){
 21         CanvasRenderer.superclass.constructor.call(this, properties);
 22 
 23         this.context = this.canvas.getContext("2d");
 24     },
 25     renderType:'canvas',
 26     context: null,
 27 
 28     /**
 29      * @private
 30      * @see Renderer#startDraw
 31      */
 32     startDraw: function(target){
 33         if(target.visible && target.alpha > 0){
 34             if(target === this.stage){
 35                 this.context.clearRect(0, 0, target.width, target.height);
 36             }
 37             this.context.save();
 38             return true;
 39         }
 40         return false;
 41     },
 42 
 43     /**
 44      * @private
 45      * @see Renderer#draw
 46      */
 47     draw: function(target){
 48         var ctx = this.context, w = target.width, h = target.height;
 49 
 50         //draw background
 51         var bg = target.background;
 52         if(bg){
 53             ctx.fillStyle = bg;
 54             ctx.fillRect(0, 0, w, h);
 55         }
 56 
 57         //draw image
 58         var drawable = target.drawable, image = drawable && drawable.image;
 59         if(image){
 60             var rect = drawable.rect, sw = rect[2], sh = rect[3], offsetX = rect[4], offsetY = rect[5];
 61             //ie9+浏览器宽高为0时会报错 fixed ie9 bug.
 62             if(!sw || !sh){
 63                 return;
 64             }
 65             if(!w && !h){
 66                 //fix width/height TODO: how to get rid of this?
 67                 w = target.width = sw;
 68                 h = target.height = sh;
 69             }
 70             //the pivot is the center of frame if has offset, otherwise is (0, 0)
 71             if(offsetX || offsetY) ctx.translate(offsetX - sw * 0.5, offsetY - sh * 0.5);
 72             ctx.drawImage(image, rect[0], rect[1], sw, sh, 0, 0, w, h);
 73         }
 74     },
 75 
 76     /**
 77      * @private
 78      * @see Renderer#endDraw
 79      */
 80     endDraw: function(target){
 81         this.context.restore();
 82     },
 83 
 84     /**
 85      * @private
 86      * @see Renderer#transform
 87      */
 88     transform: function(target){
 89         var drawable = target.drawable;
 90         if(drawable && drawable.domElement){
 91             Hilo.setElementStyleByView(target);
 92             return;
 93         }
 94 
 95         var ctx = this.context,
 96             scaleX = target.scaleX,
 97             scaleY = target.scaleY;
 98 
 99         if(target === this.stage){
100             var style = this.canvas.style,
101                 oldScaleX = target._scaleX,
102                 oldScaleY = target._scaleY;
103 
104             if((!oldScaleX && scaleX != 1) || (oldScaleX && oldScaleX != scaleX)){
105                 target._scaleX = scaleX;
106                 style.width = scaleX * target.width + "px";
107             }
108             if((!oldScaleY && scaleY != 1) || (oldScaleY && oldScaleY != scaleY)){
109                 target._scaleY = scaleY;
110                 style.height = scaleY * target.height + "px";
111             }
112         }else{
113             var x = target.x,
114                 y = target.y,
115                 pivotX = target.pivotX,
116                 pivotY = target.pivotY,
117                 rotation = target.rotation % 360,
118                 mask = target.mask;
119 
120             if(mask){
121                 mask._render(this);
122                 ctx.clip();
123             }
124 
125             //alignment
126             var align = target.align;
127             if(align){
128                 if(typeof align === 'function'){
129                     target.align();
130                 }else{
131                     var parent = target.parent;
132                     if(parent){
133                         var w = target.width, h = target.height,
134                             pw = parent.width, ph = parent.height;
135                         switch(align){
136                             case 'TL':
137                                 x = 0;
138                                 y = 0;
139                                 break;
140                             case 'T':
141                                 x = pw - w >> 1;
142                                 y = 0;
143                                 break;
144                             case 'TR':
145                                 x = pw - w;
146                                 y = 0;
147                                 break;
148                             case 'L':
149                                 x = 0;
150                                 y = ph - h >> 1;
151                                 break;
152                             case 'C':
153                                 x = pw - w >> 1;
154                                 y = ph - h >> 1;
155                                 break;
156                             case 'R':
157                                 x = pw - w;
158                                 y = ph - h >> 1;
159                                 break;
160                             case 'BL':
161                                 x = 0;
162                                 y = ph - h;
163                                 break;
164                             case 'B':
165                                 x = pw - w >> 1;
166                                 y = ph - h;
167                                 break;
168                             case 'BR':
169                                 x = pw - w;
170                                 y = ph - h;
171                                 break;
172                         }
173                     }
174                 }
175             }
176 
177             if(x != 0 || y != 0) ctx.translate(x, y);
178             if(rotation != 0) ctx.rotate(rotation * Math.PI / 180);
179             if(scaleX != 1 || scaleY != 1) ctx.scale(scaleX, scaleY);
180             if(pivotX != 0 || pivotY != 0) ctx.translate(-pivotX, -pivotY);
181         }
182 
183         if(target.alpha > 0) ctx.globalAlpha *= target.alpha;
184     },
185 
186     /**
187      * @private
188      * @see Renderer#remove
189      */
190     remove: function(target){
191         var drawable = target.drawable;
192         var elem = drawable && drawable.domElement;
193 
194         if(elem){
195             var parentElem = elem.parentNode;
196             if(parentElem){
197                 parentElem.removeChild(elem);
198             }
199         }
200     },
201 
202     /**
203      * @private
204      * @see Renderer#clear
205      */
206     clear: function(x, y, width, height){
207         this.context.clearRect(x, y, width, height);
208     },
209 
210     /**
211      * @private
212      * @see Renderer#resize
213      */
214     resize: function(width, height){
215         this.canvas.width = width;
216         this.canvas.height = height;
217     }
218 
219 });