1 /**
  2  * Hilo
  3  * Copyright 2015 alibaba.com
  4  * Licensed under the MIT License
  5  */
  6 
  7 /**
  8  * @language=en
  9  * @class DomRenderer The DomRenderer, all the visual object is drawing using dom element.The stage will create different renderer depend on the canvas and renderType properties, developer need not use this class directly.
 10  * @augments Renderer
 11  * @param {Object} properties The properties to create a renderer, contains all writeable props of this class.
 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=en
131  * Create a dom element, you can set the tagName property,such as canvas and div.
132  * @param {Object} view A visual object.
133  * @param {Object} imageObj The image object to render, include the image propertiy and other associated properties, such as rect.
134  * @return {HTMLElement} The created dom element.
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