1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @class canvas画布渲染器。所有可视对象将渲染在canvas画布上。舞台Stage会根据参数canvas选择不同的渲染器,开发者无需直接使用此类。 9 * @augments Renderer 10 * @param {Object} properties 创建对象的属性参数。可包含此类所有可写属性。 11 * @module hilo/renderer/CanvasRenderer 12 * @requires hilo/core/Class 13 * @requires hilo/core/Hilo 14 * @requires hilo/renderer/Renderer 15 * @property {CanvasRenderingContext2D} context canvas画布的上下文。只读属性。 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 });