| function CanvasRenderer(animationItem, config){ |
| this.animationItem = animationItem; |
| this.renderConfig = { |
| clearCanvas: (config && config.clearCanvas !== undefined) ? config.clearCanvas : true, |
| context: (config && config.context) || null, |
| progressiveLoad: (config && config.progressiveLoad) || false, |
| preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet' |
| }; |
| this.renderConfig.dpr = (config && config.dpr) || 1; |
| if (this.animationItem.wrapper) { |
| this.renderConfig.dpr = (config && config.dpr) || window.devicePixelRatio || 1; |
| } |
| this.renderedFrame = -1; |
| this.globalData = { |
| frameNum: -1 |
| }; |
| this.contextData = { |
| saved : Array.apply(null,{length:15}), |
| savedOp: Array.apply(null,{length:15}), |
| cArrPos : 0, |
| cTr : new Matrix(), |
| cO : 1 |
| }; |
| var i, len = 15; |
| for(i=0;i<len;i+=1){ |
| this.contextData.saved[i] = Array.apply(null,{length:16}); |
| } |
| this.elements = []; |
| this.pendingElements = []; |
| this.transformMat = new Matrix(); |
| this.completeLayers = false; |
| } |
| extendPrototype(BaseRenderer,CanvasRenderer); |
| |
| CanvasRenderer.prototype.createBase = function (data) { |
| return new CVBaseElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.createShape = function (data) { |
| return new CVShapeElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.createText = function (data) { |
| return new CVTextElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.createImage = function (data) { |
| return new CVImageElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.createComp = function (data) { |
| return new CVCompElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.createSolid = function (data) { |
| return new CVSolidElement(data, this, this.globalData); |
| }; |
| |
| CanvasRenderer.prototype.ctxTransform = function(props){ |
| if(props[0] === 1 && props[1] === 0 && props[4] === 0 && props[5] === 1 && props[12] === 0 && props[13] === 0){ |
| return; |
| } |
| if(!this.renderConfig.clearCanvas){ |
| this.canvasContext.transform(props[0],props[1],props[4],props[5],props[12],props[13]); |
| return; |
| } |
| this.transformMat.cloneFromProps(props); |
| this.transformMat.transform(this.contextData.cTr.props[0],this.contextData.cTr.props[1],this.contextData.cTr.props[2],this.contextData.cTr.props[3],this.contextData.cTr.props[4],this.contextData.cTr.props[5],this.contextData.cTr.props[6],this.contextData.cTr.props[7],this.contextData.cTr.props[8],this.contextData.cTr.props[9],this.contextData.cTr.props[10],this.contextData.cTr.props[11],this.contextData.cTr.props[12],this.contextData.cTr.props[13],this.contextData.cTr.props[14],this.contextData.cTr.props[15]) |
| //this.contextData.cTr.transform(props[0],props[1],props[2],props[3],props[4],props[5],props[6],props[7],props[8],props[9],props[10],props[11],props[12],props[13],props[14],props[15]); |
| this.contextData.cTr.cloneFromProps(this.transformMat.props); |
| var trProps = this.contextData.cTr.props; |
| this.canvasContext.setTransform(trProps[0],trProps[1],trProps[4],trProps[5],trProps[12],trProps[13]); |
| }; |
| |
| CanvasRenderer.prototype.ctxOpacity = function(op){ |
| if(op === 1){ |
| return; |
| } |
| if(!this.renderConfig.clearCanvas){ |
| this.canvasContext.globalAlpha *= op < 0 ? 0 : op; |
| return; |
| } |
| this.contextData.cO *= op < 0 ? 0 : op; |
| this.canvasContext.globalAlpha = this.contextData.cO; |
| }; |
| |
| CanvasRenderer.prototype.reset = function(){ |
| if(!this.renderConfig.clearCanvas){ |
| this.canvasContext.restore(); |
| return; |
| } |
| this.contextData.cArrPos = 0; |
| this.contextData.cTr.reset(); |
| this.contextData.cO = 1; |
| }; |
| |
| CanvasRenderer.prototype.save = function(actionFlag){ |
| if(!this.renderConfig.clearCanvas){ |
| this.canvasContext.save(); |
| return; |
| } |
| if(actionFlag){ |
| this.canvasContext.save(); |
| } |
| var props = this.contextData.cTr.props; |
| if(this.contextData.saved[this.contextData.cArrPos] === null || this.contextData.saved[this.contextData.cArrPos] === undefined){ |
| this.contextData.saved[this.contextData.cArrPos] = new Array(16); |
| } |
| var i,arr = this.contextData.saved[this.contextData.cArrPos]; |
| for(i=0;i<16;i+=1){ |
| arr[i] = props[i]; |
| } |
| this.contextData.savedOp[this.contextData.cArrPos] = this.contextData.cO; |
| this.contextData.cArrPos += 1; |
| }; |
| |
| CanvasRenderer.prototype.restore = function(actionFlag){ |
| if(!this.renderConfig.clearCanvas){ |
| this.canvasContext.restore(); |
| return; |
| } |
| if(actionFlag){ |
| this.canvasContext.restore(); |
| } |
| this.contextData.cArrPos -= 1; |
| var popped = this.contextData.saved[this.contextData.cArrPos]; |
| var i,arr = this.contextData.cTr.props; |
| for(i=0;i<16;i+=1){ |
| arr[i] = popped[i]; |
| } |
| this.canvasContext.setTransform(popped[0],popped[1],popped[4],popped[5],popped[12],popped[13]); |
| popped = this.contextData.savedOp[this.contextData.cArrPos]; |
| this.contextData.cO = popped; |
| this.canvasContext.globalAlpha = popped; |
| }; |
| |
| CanvasRenderer.prototype.configAnimation = function(animData){ |
| if(this.animationItem.wrapper){ |
| this.animationItem.container = document.createElement('canvas'); |
| this.animationItem.container.style.width = '100%'; |
| this.animationItem.container.style.height = '100%'; |
| //this.animationItem.container.style.transform = 'translate3d(0,0,0)'; |
| //this.animationItem.container.style.webkitTransform = 'translate3d(0,0,0)'; |
| this.animationItem.container.style.transformOrigin = this.animationItem.container.style.mozTransformOrigin = this.animationItem.container.style.webkitTransformOrigin = this.animationItem.container.style['-webkit-transform'] = "0px 0px 0px"; |
| this.animationItem.wrapper.appendChild(this.animationItem.container); |
| this.canvasContext = this.animationItem.container.getContext('2d'); |
| }else{ |
| this.canvasContext = this.renderConfig.context; |
| } |
| this.data = animData; |
| this.globalData.canvasContext = this.canvasContext; |
| this.globalData.renderer = this; |
| this.globalData.isDashed = false; |
| this.globalData.totalFrames = Math.floor(animData.tf); |
| this.globalData.compWidth = animData.w; |
| this.globalData.compHeight = animData.h; |
| this.globalData.frameRate = animData.fr; |
| this.globalData.frameId = 0; |
| this.globalData.compSize = { |
| w: animData.w, |
| h: animData.h |
| }; |
| this.globalData.progressiveLoad = this.renderConfig.progressiveLoad; |
| this.layers = animData.layers; |
| this.transformCanvas = {}; |
| this.transformCanvas.w = animData.w; |
| this.transformCanvas.h = animData.h; |
| this.globalData.fontManager = new FontManager(); |
| this.globalData.fontManager.addChars(animData.chars); |
| this.globalData.fontManager.addFonts(animData.fonts,document.body); |
| this.globalData.getAssetData = this.animationItem.getAssetData.bind(this.animationItem); |
| this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem); |
| this.globalData.elementLoaded = this.animationItem.elementLoaded.bind(this.animationItem); |
| this.globalData.addPendingElement = this.animationItem.addPendingElement.bind(this.animationItem); |
| this.globalData.transformCanvas = this.transformCanvas; |
| this.elements = Array.apply(null,{length:animData.layers.length}); |
| |
| this.updateContainerSize(); |
| }; |
| |
| CanvasRenderer.prototype.updateContainerSize = function () { |
| var elementWidth,elementHeight; |
| if(this.animationItem.wrapper && this.animationItem.container){ |
| elementWidth = this.animationItem.wrapper.offsetWidth; |
| elementHeight = this.animationItem.wrapper.offsetHeight; |
| this.animationItem.container.setAttribute('width',elementWidth * this.renderConfig.dpr ); |
| this.animationItem.container.setAttribute('height',elementHeight * this.renderConfig.dpr); |
| }else{ |
| elementWidth = this.canvasContext.canvas.width * this.renderConfig.dpr; |
| elementHeight = this.canvasContext.canvas.height * this.renderConfig.dpr; |
| } |
| var elementRel,animationRel; |
| if(this.renderConfig.preserveAspectRatio.indexOf('meet') !== -1 || this.renderConfig.preserveAspectRatio.indexOf('slice') !== -1){ |
| var par = this.renderConfig.preserveAspectRatio.split(' '); |
| var fillType = par[1] || 'meet'; |
| var pos = par[0] || 'xMidYMid'; |
| var xPos = pos.substr(0,4); |
| var yPos = pos.substr(4); |
| elementRel = elementWidth/elementHeight; |
| animationRel = this.transformCanvas.w/this.transformCanvas.h; |
| if(animationRel>elementRel && fillType === 'meet' || animationRel<elementRel && fillType === 'slice'){ |
| this.transformCanvas.sx = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr); |
| this.transformCanvas.sy = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr); |
| }else{ |
| this.transformCanvas.sx = elementHeight/(this.transformCanvas.h / this.renderConfig.dpr); |
| this.transformCanvas.sy = elementHeight/(this.transformCanvas.h / this.renderConfig.dpr); |
| } |
| |
| if(xPos === 'xMid' && ((animationRel<elementRel && fillType==='meet') || (animationRel>elementRel && fillType === 'slice'))){ |
| this.transformCanvas.tx = (elementWidth-this.transformCanvas.w*(elementHeight/this.transformCanvas.h))/2*this.renderConfig.dpr; |
| } else if(xPos === 'xMax' && ((animationRel<elementRel && fillType==='meet') || (animationRel>elementRel && fillType === 'slice'))){ |
| this.transformCanvas.tx = (elementWidth-this.transformCanvas.w*(elementHeight/this.transformCanvas.h))*this.renderConfig.dpr; |
| } else { |
| this.transformCanvas.tx = 0; |
| } |
| if(yPos === 'YMid' && ((animationRel>elementRel && fillType==='meet') || (animationRel<elementRel && fillType === 'slice'))){ |
| this.transformCanvas.ty = ((elementHeight-this.transformCanvas.h*(elementWidth/this.transformCanvas.w))/2)*this.renderConfig.dpr; |
| } else if(yPos === 'YMax' && ((animationRel>elementRel && fillType==='meet') || (animationRel<elementRel && fillType === 'slice'))){ |
| this.transformCanvas.ty = ((elementHeight-this.transformCanvas.h*(elementWidth/this.transformCanvas.w)))*this.renderConfig.dpr; |
| } else { |
| this.transformCanvas.ty = 0; |
| } |
| |
| }else if(this.renderConfig.preserveAspectRatio == 'none'){ |
| this.transformCanvas.sx = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr); |
| this.transformCanvas.sy = elementHeight/(this.transformCanvas.h/this.renderConfig.dpr); |
| this.transformCanvas.tx = 0; |
| this.transformCanvas.ty = 0; |
| }else{ |
| this.transformCanvas.sx = this.renderConfig.dpr; |
| this.transformCanvas.sy = this.renderConfig.dpr; |
| this.transformCanvas.tx = 0; |
| this.transformCanvas.ty = 0; |
| } |
| this.transformCanvas.props = [this.transformCanvas.sx,0,0,0,0,this.transformCanvas.sy,0,0,0,0,1,0,this.transformCanvas.tx,this.transformCanvas.ty,0,1]; |
| var i, len = this.elements.length; |
| for(i=0;i<len;i+=1){ |
| if(this.elements[i] && this.elements[i].data.ty === 0){ |
| this.elements[i].resize(this.globalData.transformCanvas); |
| } |
| } |
| }; |
| |
| CanvasRenderer.prototype.destroy = function () { |
| if(this.renderConfig.clearCanvas) { |
| this.animationItem.wrapper.innerHTML = ''; |
| } |
| var i, len = this.layers ? this.layers.length : 0; |
| for (i = len - 1; i >= 0; i-=1) { |
| this.elements[i].destroy(); |
| } |
| this.elements.length = 0; |
| this.globalData.canvasContext = null; |
| this.animationItem.container = null; |
| this.destroyed = true; |
| }; |
| |
| CanvasRenderer.prototype.renderFrame = function(num){ |
| if((this.renderedFrame == num && this.renderConfig.clearCanvas === true) || this.destroyed || num === null){ |
| return; |
| } |
| this.renderedFrame = num; |
| this.globalData.frameNum = num - this.animationItem.firstFrame; |
| this.globalData.frameId += 1; |
| this.globalData.projectInterface.currentFrame = num; |
| if(this.renderConfig.clearCanvas === true){ |
| this.reset(); |
| this.canvasContext.save(); |
| //this.canvasContext.canvas.width = this.canvasContext.canvas.width; |
| this.canvasContext.clearRect(this.transformCanvas.tx, this.transformCanvas.ty, this.transformCanvas.w*this.transformCanvas.sx, this.transformCanvas.h*this.transformCanvas.sy); |
| }else{ |
| this.save(); |
| } |
| this.ctxTransform(this.transformCanvas.props); |
| this.canvasContext.beginPath(); |
| this.canvasContext.rect(0,0,this.transformCanvas.w,this.transformCanvas.h); |
| this.canvasContext.closePath(); |
| this.canvasContext.clip(); |
| |
| //console.log('--------'); |
| //console.log('NEW: ',num); |
| var i, len = this.layers.length; |
| if(!this.completeLayers){ |
| this.checkLayers(num); |
| } |
| |
| for (i = 0; i < len; i++) { |
| if(this.completeLayers || this.elements[i]){ |
| this.elements[i].prepareFrame(num - this.layers[i].st); |
| } |
| } |
| for (i = len - 1; i >= 0; i-=1) { |
| if(this.completeLayers || this.elements[i]){ |
| this.elements[i].renderFrame(); |
| } |
| } |
| if(this.renderConfig.clearCanvas !== true){ |
| this.restore(); |
| } else { |
| this.canvasContext.restore(); |
| } |
| }; |
| |
| CanvasRenderer.prototype.buildItem = function(pos){ |
| var elements = this.elements; |
| if(elements[pos] || this.layers[pos].ty == 99){ |
| return; |
| } |
| var element = this.createItem(this.layers[pos], this,this.globalData); |
| elements[pos] = element; |
| element.initExpressions(); |
| if(this.layers[pos].ty === 0){ |
| element.resize(this.globalData.transformCanvas); |
| } |
| }; |
| |
| CanvasRenderer.prototype.checkPendingElements = function(){ |
| while(this.pendingElements.length){ |
| var element = this.pendingElements.pop(); |
| element.checkParenting(); |
| } |
| }; |
| |
| CanvasRenderer.prototype.hide = function(){ |
| this.animationItem.container.style.display = 'none'; |
| }; |
| |
| CanvasRenderer.prototype.show = function(){ |
| this.animationItem.container.style.display = 'block'; |
| }; |
| |
| CanvasRenderer.prototype.searchExtraCompositions = function(assets){ |
| var i, len = assets.length; |
| var floatingContainer = document.createElementNS(svgNS,'g'); |
| for(i=0;i<len;i+=1){ |
| if(assets[i].xt){ |
| var comp = this.createComp(assets[i],this.globalData.comp,this.globalData); |
| comp.initExpressions(); |
| //comp.compInterface = CompExpressionInterface(comp); |
| //Expressions.addLayersInterface(comp.elements, this.globalData.projectInterface); |
| this.globalData.projectInterface.registerComposition(comp); |
| } |
| } |
| }; |