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