1 /**
  2  * Hilo
  3  * Copyright 2015 alibaba.com
  4  * Licensed under the MIT License
  5  */
  6 
  7 /**
  8  * @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.
  9  * @augments Renderer
 10  * @param {Object} properties The properties to create a renderer, contains all writeable props of this class.
 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  * Create a dom element, you can set the tagName property,such as canvas and div.
130  * @param {Object} view A visual object.
131  * @param {Object} imageObj The image object to render, include the image propertiy and other associated properties, such as rect.
132  * @return {HTMLElement} The created dom element.
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