1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @class CanvasRenderer CanvasRenderer, all the visual object is drawing on the canvas 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/CanvasRenderer 12 * @requires hilo/core/Class 13 * @requires hilo/core/Hilo 14 * @requires hilo/renderer/Renderer 15 * @property {CanvasRenderingContext2D} context The context of the canvas element, readonly. 16 */ 17 var CanvasRenderer = Class.create( /** @lends CanvasRenderer.prototype */ { 18 Extends: Renderer, 19 constructor: function(properties) { 20 CanvasRenderer.superclass.constructor.call(this, properties); 21 22 this.context = this.canvas.getContext("2d"); 23 }, 24 renderType: 'canvas', 25 context: null, 26 27 /** 28 * @private 29 * @see Renderer#startDraw 30 */ 31 startDraw: function(target) { 32 if (target.visible && target.alpha > 0) { 33 if (target === this.stage) { 34 this.context.clearRect(0, 0, target.width, target.height); 35 } 36 if (target.blendMode !== this.blendMode) { 37 this.context.globalCompositeOperation = this.blendMode = target.blendMode; 38 } 39 this.context.save(); 40 return true; 41 } 42 return false; 43 }, 44 45 /** 46 * @private 47 * @see Renderer#draw 48 */ 49 draw: function(target) { 50 var ctx = this.context, 51 w = target.width, 52 h = target.height; 53 54 //draw background 55 var bg = target.background; 56 if (bg) { 57 ctx.fillStyle = bg; 58 ctx.fillRect(0, 0, w, h); 59 } 60 61 //draw image 62 var drawable = target.drawable, 63 image = drawable && drawable.image; 64 if (image) { 65 var rect = drawable.rect, 66 sw = rect[2], 67 sh = rect[3], 68 offsetX = rect[4], 69 offsetY = rect[5]; 70 //ie9+浏览器宽高为0时会报错 fixed ie9 bug. 71 if (!sw || !sh) { 72 return; 73 } 74 if (!w && !h) { 75 //fix width/height TODO: how to get rid of this? 76 w = target.width = sw; 77 h = target.height = sh; 78 } 79 //the pivot is the center of frame if has offset, otherwise is (0, 0) 80 if (offsetX || offsetY) ctx.translate(offsetX - sw * 0.5, offsetY - sh * 0.5); 81 ctx.drawImage(image, rect[0], rect[1], sw, sh, 0, 0, w, h); 82 } 83 }, 84 85 /** 86 * @private 87 * @see Renderer#endDraw 88 */ 89 endDraw: function(target) { 90 this.context.restore(); 91 }, 92 93 /** 94 * @private 95 * @see Renderer#transform 96 */ 97 transform: function(target) { 98 var drawable = target.drawable; 99 if (drawable && drawable.domElement) { 100 Hilo.setElementStyleByView(target); 101 return; 102 } 103 104 var ctx = this.context, 105 scaleX = target.scaleX, 106 scaleY = target.scaleY; 107 108 if (target === this.stage) { 109 var style = this.canvas.style, 110 oldScaleX = target._scaleX, 111 oldScaleY = target._scaleY, 112 isStyleChange = false; 113 114 if ((!oldScaleX && scaleX != 1) || (oldScaleX && oldScaleX != scaleX)) { 115 target._scaleX = scaleX; 116 style.width = scaleX * target.width + "px"; 117 isStyleChange = true; 118 } 119 if ((!oldScaleY && scaleY != 1) || (oldScaleY && oldScaleY != scaleY)) { 120 target._scaleY = scaleY; 121 style.height = scaleY * target.height + "px"; 122 isStyleChange = true; 123 } 124 if (isStyleChange) { 125 target.updateViewport(); 126 } 127 } else { 128 var x = target.x, 129 y = target.y, 130 pivotX = target.pivotX, 131 pivotY = target.pivotY, 132 rotation = target.rotation % 360, 133 transform = target.transform, 134 mask = target.mask; 135 136 if (mask) { 137 mask._render(this); 138 ctx.clip(); 139 } 140 141 //alignment 142 var align = target.align; 143 if (align) { 144 var pos = target.getAlignPosition(); 145 x = pos.x; 146 y = pos.y; 147 } 148 149 if (transform) { 150 ctx.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); 151 } else { 152 if (x != 0 || y != 0) ctx.translate(x, y); 153 if (rotation != 0) ctx.rotate(rotation * Math.PI / 180); 154 if (scaleX != 1 || scaleY != 1) ctx.scale(scaleX, scaleY); 155 if (pivotX != 0 || pivotY != 0) ctx.translate(-pivotX, -pivotY); 156 } 157 158 } 159 160 if (target.alpha > 0) ctx.globalAlpha *= target.alpha; 161 }, 162 163 /** 164 * @private 165 * @see Renderer#remove 166 */ 167 remove: function(target) { 168 var drawable = target.drawable; 169 var elem = drawable && drawable.domElement; 170 171 if (elem) { 172 var parentElem = elem.parentNode; 173 if (parentElem) { 174 parentElem.removeChild(elem); 175 } 176 } 177 }, 178 179 /** 180 * @private 181 * @see Renderer#clear 182 */ 183 clear: function(x, y, width, height) { 184 this.context.clearRect(x, y, width, height); 185 }, 186 187 /** 188 * @private 189 * @see Renderer#resize 190 */ 191 resize: function(width, height) { 192 var canvas = this.canvas; 193 var stage = this.stage; 194 var style = canvas.style; 195 196 canvas.width = width; 197 canvas.height = height; 198 199 style.width = stage.width * stage.scaleX + 'px'; 200 style.height = stage.height * stage.scaleY + 'px'; 201 } 202 203 });