/** * Hilo * Copyright 2015 alibaba.com * Licensed under the MIT License */ /** * @class canvas画布渲染器。所有可视对象将渲染在canvas画布上。舞台Stage会根据参数canvas选择不同的渲染器,开发者无需直接使用此类。 * @augments Renderer * @param {Object} properties 创建对象的属性参数。可包含此类所有可写属性。 * @module hilo/renderer/CanvasRenderer * @requires hilo/core/Class * @requires hilo/core/Hilo * @requires hilo/renderer/Renderer * @property {CanvasRenderingContext2D} context canvas画布的上下文。只读属性。 */ var CanvasRenderer = Class.create( /** @lends CanvasRenderer.prototype */ { Extends: Renderer, constructor: function(properties) { CanvasRenderer.superclass.constructor.call(this, properties); this.context = this.canvas.getContext("2d"); }, renderType: 'canvas', context: null, /** * @private * @see Renderer#startDraw */ startDraw: function(target) { if (target.visible && target.alpha > 0) { if (target === this.stage) { this.context.clearRect(0, 0, target.width, target.height); } if (target.blendMode !== this.blendMode) { this.context.globalCompositeOperation = this.blendMode = target.blendMode; } this.context.save(); return true; } return false; }, /** * @private * @see Renderer#draw */ draw: function(target) { var ctx = this.context, w = target.width, h = target.height; //draw background var bg = target.background; if (bg) { ctx.fillStyle = bg; ctx.fillRect(0, 0, w, h); } //draw image var drawable = target.drawable, image = drawable && drawable.image; if (image) { var rect = drawable.rect, sw = rect[2], sh = rect[3], offsetX = rect[4], offsetY = rect[5]; //ie9+浏览器宽高为0时会报错 fixed ie9 bug. if (!sw || !sh) { return; } if (!w && !h) { //fix width/height TODO: how to get rid of this? w = target.width = sw; h = target.height = sh; } //the pivot is the center of frame if has offset, otherwise is (0, 0) if (offsetX || offsetY) ctx.translate(offsetX - sw * 0.5, offsetY - sh * 0.5); ctx.drawImage(image, rect[0], rect[1], sw, sh, 0, 0, w, h); } }, /** * @private * @see Renderer#endDraw */ endDraw: function(target) { this.context.restore(); }, /** * @private * @see Renderer#transform */ transform: function(target) { var drawable = target.drawable; if (drawable && drawable.domElement) { Hilo.setElementStyleByView(target); return; } var ctx = this.context, scaleX = target.scaleX, scaleY = target.scaleY; if (target === this.stage) { var style = this.canvas.style, oldScaleX = target._scaleX, oldScaleY = target._scaleY, isStyleChange = false; if ((!oldScaleX && scaleX != 1) || (oldScaleX && oldScaleX != scaleX)) { target._scaleX = scaleX; style.width = scaleX * target.width + "px"; isStyleChange = true; } if ((!oldScaleY && scaleY != 1) || (oldScaleY && oldScaleY != scaleY)) { target._scaleY = scaleY; style.height = scaleY * target.height + "px"; isStyleChange = true; } if (isStyleChange) { target.updateViewport(); } } else { var x = target.x, y = target.y, pivotX = target.pivotX, pivotY = target.pivotY, rotation = target.rotation % 360, transform = target.transform, mask = target.mask; if (mask) { mask._render(this); ctx.clip(); } //alignment var align = target.align; if (align) { var pos = target.getAlignPosition(); x = pos.x; y = pos.y; } if (transform) { ctx.transform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); } else { if (x != 0 || y != 0) ctx.translate(x, y); if (rotation != 0) ctx.rotate(rotation * Math.PI / 180); if (scaleX != 1 || scaleY != 1) ctx.scale(scaleX, scaleY); if (pivotX != 0 || pivotY != 0) ctx.translate(-pivotX, -pivotY); } } if (target.alpha > 0) ctx.globalAlpha *= target.alpha; }, /** * @private * @see Renderer#remove */ remove: function(target) { var drawable = target.drawable; var elem = drawable && drawable.domElement; if (elem) { var parentElem = elem.parentNode; if (parentElem) { parentElem.removeChild(elem); } } }, /** * @private * @see Renderer#clear */ clear: function(x, y, width, height) { this.context.clearRect(x, y, width, height); }, /** * @private * @see Renderer#resize */ resize: function(width, height) { var canvas = this.canvas; var stage = this.stage; var style = canvas.style; canvas.width = width; canvas.height = height; style.width = stage.width * stage.scaleX + 'px'; style.height = stage.height * stage.scaleY + 'px'; } });