blob: 7b111274dfcf7cf8d4a67080aee8374e80ad6ce8 [file] [edit]
var AnimationItem = function () {
this.name = '';
this.path = '';
this.isLoaded = false;
this.currentFrame = 0;
this.currentRawFrame = 0;
this.totalFrames = 0;
this.frameRate = 0;
this.frameMult = 0;
this.playSpeed = 1;
this.playDirection = 1;
this.pendingElements = 0;
this.repeat = 'indefinite';
this.animationData = {};
this.layers = [];
this.assets = [];
this.renderedFrames = {};
this.effectsManager = null;
this.isPaused = true;
this.isScrolling = false;
this.loop = true;
};
AnimationItem.prototype.setData = function (wrapper) {
this.wrapper = wrapper;
//this.wrapper.style.position = 'relative';
var self = this;
this.path = this.wrapper.attributes.getNamedItem("data-animation-path") ? this.wrapper.attributes.getNamedItem("data-animation-path").value : '';
this.playerType = this.wrapper.attributes.getNamedItem("data-bm-player") ? this.wrapper.attributes.getNamedItem("data-bm-player").value : '0';
this.animType = this.wrapper.attributes.getNamedItem("data-anim-type") ? this.wrapper.attributes.getNamedItem("data-anim-type").value : 'div';
this.containerType = 'svg';
this.repeat = this.wrapper.attributes.getNamedItem("data-anim-repeat") ? this.wrapper.attributes.getNamedItem("data-anim-repeat").value : this.repeat;
this.loop = this.wrapper.attributes.getNamedItem("data-anim-loop") ? this.wrapper.attributes.getNamedItem("data-anim-loop").value !== 'false' : this.loop;
this.name = this.wrapper.attributes.getNamedItem("data-name") ? this.wrapper.attributes.getNamedItem("data-name").value : '';
if(this.path == ''){
return;
}
if (this.path.substr(-1, 1) != '/') {
this.path += "/";
}
var xhr = new XMLHttpRequest();
xhr.open("GET", this.path + 'data.json', true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
self.configAnimation(JSON.parse(xhr.responseText));
}
};
};
AnimationItem.prototype.configAnimation = function (animData) {
this.container = document.createElementNS(svgNS,'svg');
this.container.setAttribute('xmlns','http://www.w3.org/2000/svg');
this.container.setAttribute('width',animData.animation.compWidth);
this.container.setAttribute('height',animData.animation.compHeight);
this.container.setAttribute('viewBox','0 0 '+animData.animation.compWidth+' '+animData.animation.compHeight);
this.container.setAttribute('preserveAspectRatio','xMidYMid meet');
this.container.style.width = '100%';
this.container.style.height = '100%';
this.container.style.transformOrigin = this.container.style.mozTransformOrigin = this.container.style.webkitTransformOrigin = this.container.style['-webkit-transform'] = "0px 0px 0px";
//this.container.style.overflow = 'hidden';
//styleDiv(this.container);
this.wrapper.appendChild(this.container);
//Mask animation
var defs = document.createElementNS(svgNS, 'defs');
this.container.appendChild(defs);
var maskElement = document.createElementNS(svgNS, 'clipPath');
var rect = document.createElementNS(svgNS,'rect');
rect.setAttribute('width',animData.animation.compWidth);
rect.setAttribute('height',animData.animation.compHeight);
rect.setAttribute('x',0);
rect.setAttribute('y',0);
maskElement.setAttribute('id', 'animationMask');
maskElement.appendChild(rect);
var maskedElement = document.createElementNS(svgNS,'g');
maskedElement.setAttribute("clip-path", "url(#animationMask)");
this.container.appendChild(maskedElement);
defs.appendChild(maskElement);
this.container = maskedElement;
this.effectsManager = new EffectsManager();
this.animationData = animData;
this.layers = this.animationData.animation.layers;
this.assets = this.animationData.assets;
this.totalFrames = this.animationData.animation.totalFrames;
this.frameRate = this.animationData.animation.frameRate;
this.frameMult = this.animationData.animation.frameRate / 1000;
dataManager.completeData(this.layers, this.frameRate);
this.buildItems(this.animationData.animation.layers, this.containerType);
this.updaFrameModifier();
this.checkLoaded();
};
AnimationItem.prototype.buildItems = function (layers, type) {
var count = 0, i, len = layers.length;
for (i = 0; i < len; i++) {
if (layers[i].type == 'StillLayer') {
count++;
this.createImage(layers[i], type);
} else if (layers[i].type == 'PreCompLayer') {
this.createComp(layers[i], type);
} else if (layers[i].type == 'SolidLayer') {
this.createSolid(layers[i], type);
} else if (layers[i].type == 'ShapeLayer') {
this.createShape(layers[i], type);
} else if (layers[i].type == 'TextLayer') {
this.createText(layers[i], type);
}else{
console.log('NO TYPE: ',layers[i]);
}
}
this.pendingElements += count;
};
AnimationItem.prototype.createShape = function (data, type) {
data.element = new IShapeElement(data, type, this);
};
AnimationItem.prototype.createText = function (data, type) {
data.element = new ITextElement(data, type, this);
};
AnimationItem.prototype.createImage = function (data, type) {
data.element = new IImageElement(data, type, this);
};
AnimationItem.prototype.createComp = function (data, type) {
data.element = new ICompElement(data, type, this);
this.buildItems(data.layers, data.element.getType());
};
AnimationItem.prototype.createSolid = function (data, type) {
data.element = new ISolidElement(data, type, this);
};
AnimationItem.prototype.elementLoaded = function () {
this.pendingElements--;
this.checkLoaded();
};
AnimationItem.prototype.checkLoaded = function () {
if (this.pendingElements == 0) {
this.isLoaded = true;
this.buildStage(this.container, this.layers, this.containerType);
this.buildControls();
this.gotoFrame();
//TODO Need polyfill for ios 5.1
this.dispatchEvent('bmLoaded');
}
};
AnimationItem.prototype.buildStage = function (container, layers, parentType) {
var i, len = layers.length, layerData;
for (i = len - 1; i >= 0; i--) {
layerData = layers[i];
if (layerData.parent) {
var mainContainer = this.buildItemHierarchy(layerData.element.getDomElement(), layerData.layerName, layerData.parent, layers, container, parentType);
mainContainer.setAttribute("data-layer-name", layerData.layerName);
container.appendChild(mainContainer);
layerData.element.setMainElement(mainContainer);
} else {
layerData.element.getDomElement().setAttribute("data-layer-name", layerData.layerName);
container.appendChild(layerData.element.getDomElement());
layerData.element.setMainElement(layerData.element.getDomElement());
}
if (layerData.type == 'PreCompLayer') {
this.buildStage(layerData.element.getComposingElement(), layerData.layers, layerData.element.getType());
}
}
};
AnimationItem.prototype.buildItemHierarchy = function (threeItem, layerName, parentName, layers, container, parentType) {
var i = 0, len = layers.length;
while (i < len) {
if (layers[i].layerName == parentName) {
if (!layers[i].relateds) {
layers[i].relateds = [];
}
var div, itemCont;
if (parentType == 'svg') {
div = document.createElementNS(svgNS, 'g');
itemCont = document.createElementNS(svgNS, 'g');
} else {
div = document.createElement('div');
styleDiv(div);
itemCont = document.createElement('div');
styleDiv(itemCont);
}
layers[i].relateds.push({item:div, itemCont:itemCont, type:parentType});
div.appendChild(threeItem);
itemCont.appendChild(div);
if (layers[i].parent == undefined) {
} else {
return this.buildItemHierarchy(itemCont, layerName, layers[i].parent, layers, container, parentType);
}
return itemCont;
}
i += 1;
}
return null;
};
AnimationItem.prototype.buildControls = function () {
if(this.playerType === '0'){
return;
}
this.player = playerManager.createPlayer(this.playerType);
this.player.buildControls(this,this.wrapper);
};
AnimationItem.prototype.gotoFrame = function () {
if(subframeEnabled){
this.renderedFrames = [];
this.currentFrame = this.currentRawFrame;
}else{
this.currentFrame = Math.floor(this.currentRawFrame);
}
this.renderFrame(this.layers);
if(this.player){
this.player.setProgress(this.currentFrame / this.totalFrames);
}
};
AnimationItem.prototype.renderFrame = function (layers) {
if(this.isLoaded === false){
return;
}
if(!this.renderedFrames[this.currentFrame]){
this.renderedFrames[this.currentFrame] = true;
dataManager.renderFrame(this.layers,this.currentFrame);
}
var i, len = layers.length;
for (i = 0; i < len; i++) {
layers[i].element.renderFrame(this.currentFrame - layers[i].startTime);
}
};
AnimationItem.prototype.dispatchEvent = function(eventName){
var event;
if(document.createEvent){
event = document.createEvent("CustomEvent");
event.initCustomEvent(eventName, false, false, {});
}else{
event = new CustomEvent('bmPlay');
//this.wrapper.dispatchEvent(event);
}
this.wrapper.dispatchEvent(event);
};
AnimationItem.prototype.play = function (name) {
if(name && this.name != name){
return;
}
if(this.isPaused === true){
this.isPaused = false;
this.dispatchEvent('bmPlay');
}
};
AnimationItem.prototype.pause = function (name) {
if(name && this.name != name){
return;
}
if(this.isPaused === false){
this.isPaused = true;
this.dispatchEvent('bmPause');
}
};
AnimationItem.prototype.togglePause = function (name) {
if(name && this.name != name){
return;
}
if(this.isPaused === false){
this.play();
}else{
this.pause();
}
};
AnimationItem.prototype.stop = function (name) {
if(name && this.name != name){
return;
}
this.isPaused = true;
this.currentFrame = this.currentRawFrame = 0;
this.dispatchEvent('bmStop');
};
AnimationItem.prototype.goToAndStop = function (pos) {
this.isPaused = true;
this.currentFrame = this.currentRawFrame = pos;
this.gotoFrame();
};
AnimationItem.prototype.advanceTime = function (value) {
if (this.isPaused === true || this.isScrolling === true || this.isLoaded === false) {
return;
}
this.setCurrentRawFrameValue(this.currentRawFrame + value * this.frameModifier);
};
AnimationItem.prototype.updateAnimation = function (perc) {
this.setCurrentRawFrameValue(this.totalFrames * perc);
};
AnimationItem.prototype.moveFrame = function (value, name) {
if(name && this.name != name){
return;
}
this.setCurrentRawFrameValue(this.currentRawFrame+value);
};
AnimationItem.prototype.setCurrentRawFrameValue = function(value){
this.currentRawFrame = value;
if (this.currentRawFrame >= this.totalFrames) {
this.currentRawFrame = this.currentRawFrame % this.totalFrames;
if(this.loop === false){
this.goToAndStop(this.totalFrames - 1);
}
} else if (this.currentRawFrame < 0) {
this.currentRawFrame = this.totalFrames + this.currentRawFrame;
}
this.gotoFrame();
};
AnimationItem.prototype.setSpeed = function (val) {
this.playSpeed = val;
this.updaFrameModifier();
};
AnimationItem.prototype.setDirection = function (val) {
this.playDirection = val < 0 ? -1 : 1;
this.updaFrameModifier();
};
AnimationItem.prototype.updaFrameModifier = function () {
this.frameModifier = this.frameMult * this.playSpeed * this.playDirection;
};
AnimationItem.prototype.getPath = function () {
return this.path;
};
AnimationItem.prototype.getAssets = function () {
return this.assets;
};