1 /**
  2  * Hilo
  3  * Copyright 2015 alibaba.com
  4  * Licensed under the MIT License
  5  */
  6 
  7 /**
  8  * @class DOM+CSS3渲染器。将可视对象以DOM元素方式渲染出来。舞台Stage会根据参数canvas选择不同的渲染器,开发者无需直接使用此类。
  9  * @augments Renderer
 10  * @param {Object} properties 创建对象的属性参数。可包含此类所有可写属性。
 11  * @module hilo/renderer/DOMRenderer
 12  * @requires hilo/core/Class
 13  * @requires hilo/core/Hilo
 14  * @requires hilo/renderer/Renderer
 15  * @requires hilo/view/Drawable
 16  */
 17 var DOMRenderer = (function(){
 18 
 19 return Class.create({
 20     Extends: Renderer,
 21     constructor: function(properties){
 22         DOMRenderer.superclass.constructor.call(this, properties);
 23     },
 24     renderType:'dom',
 25     /**
 26      * @private
 27      * @see Renderer#startDraw
 28      */
 29     startDraw: function(target){
 30         //prepare drawable
 31         var drawable = (target.drawable = target.drawable || new Drawable());
 32         drawable.domElement = drawable.domElement || createDOMDrawable(target, drawable);
 33         return true;
 34     },
 35 
 36     /**
 37      * @private
 38      * @see Renderer#draw
 39      */
 40     draw: function(target){
 41         var parent = target.parent,
 42             targetElem = target.drawable.domElement,
 43             currentParent = targetElem.parentNode;
 44 
 45         if(parent){
 46             var parentElem = parent.drawable.domElement;
 47             if(parentElem != currentParent){
 48                 parentElem.appendChild(targetElem);
 49             }
 50             //fix image load bug
 51             if(!target.width && !target.height){
 52                 var rect = target.drawable.rect;
 53                 if(rect && (rect[2] || rect[3])){
 54                     target.width = rect[2];
 55                     target.height = rect[3];
 56                 }
 57             }
 58         }
 59         else if(target === this.stage && !currentParent){
 60             targetElem.style.overflow = 'hidden';
 61             this.canvas.appendChild(targetElem);
 62         }
 63     },
 64 
 65     /**
 66      * @private
 67      * @see Renderer#transform
 68      */
 69     transform: function(target){
 70         Hilo.setElementStyleByView(target);
 71         if(target === this.stage){
 72             var style = this.canvas.style,
 73                 oldScaleX = target._scaleX,
 74                 oldScaleY = target._scaleY,
 75                 scaleX = target.scaleX,
 76                 scaleY = target.scaleY;
 77 
 78             if((!oldScaleX && scaleX != 1) || (oldScaleX && oldScaleX != scaleX)){
 79                 target._scaleX = scaleX;
 80                 style.width = scaleX * target.width + "px";
 81             }
 82             if((!oldScaleY && scaleY != 1) || (oldScaleY && oldScaleY != scaleY)){
 83                 target._scaleY = scaleY;
 84                 style.height = scaleY * target.height + "px";
 85             }
 86         }
 87     },
 88 
 89     /**
 90      * @private
 91      * @see Renderer#remove
 92      */
 93     remove: function(target){
 94         var drawable = target.drawable;
 95         var elem = drawable && drawable.domElement;
 96 
 97         if(elem){
 98             var parentElem = elem.parentNode;
 99             if(parentElem){
100                 parentElem.removeChild(elem);
101             }
102         }
103     },
104 
105     /**
106      * @private
107      * @see Renderer#hide
108      */
109     hide: function(target){
110         var elem = target.drawable && target.drawable.domElement;
111         if(elem) elem.style.display = 'none';
112     },
113 
114     /**
115      * @private
116      * @see Renderer#resize
117      */
118     resize: function(width, height){
119         var style = this.canvas.style;
120         style.width = width + 'px';
121         style.height = height + 'px';
122         if(style.position != "absolute") {
123           style.position = "relative";
124         }
125     }
126 });
127 
128 /**
129  * 创建一个可渲染的DOM,可指定tagName,如canvas或div。
130  * @param {Object} view 一个可视对象或类似的对象。
131  * @param {Object} imageObj 指定渲染的image及相关设置,如绘制区域rect。
132  * @return {HTMLElement} 新创建的DOM对象。
133  * @private
134  */
135 function createDOMDrawable(view, imageObj){
136     var tag = view.tagName || "div",
137         img = imageObj.image,
138         w = view.width || (img && img.width),
139         h =  view.height || (img && img.height),
140         elem = Hilo.createElement(tag), style = elem.style;
141 
142     if(view.id) elem.id = view.id;
143     style.position = "absolute";
144     style.left = (view.left || 0) + "px";
145     style.top = (view.top || 0) + "px";
146     style.width = w + "px";
147     style.height = h + "px";
148 
149     if(tag == "canvas"){
150         elem.width = w;
151         elem.height = h;
152         if(img){
153             var ctx = elem.getContext("2d");
154             var rect = imageObj.rect || [0, 0, w, h];
155             ctx.drawImage(img, rect[0], rect[1], rect[2], rect[3],
156                          (view.x || 0), (view.y || 0),
157                          (view.width || rect[2]),
158                          (view.height || rect[3]));
159         }
160     }else{
161         style.opacity = view.alpha != undefined ? view.alpha : 1;
162         if(view === this.stage || view.clipChildren) style.overflow = "hidden";
163         if(img && img.src){
164             style.backgroundImage = "url(" + img.src + ")";
165             var bgX = view.rectX || 0, bgY = view.rectY || 0;
166             style.backgroundPosition = (-bgX) + "px " + (-bgY) + "px";
167         }
168     }
169     return elem;
170 }
171 
172 })();
173