      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