diff --git a/build/player/lottie.js b/build/player/lottie.js index a3919efc7..0202f331c 100644 --- a/build/player/lottie.js +++ b/build/player/lottie.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6656,6 +6669,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8398,6 +8419,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -10598,13 +10697,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -11125,6 +11243,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -11410,6 +11793,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -11474,6 +11864,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -11757,6 +12148,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -11772,6 +12175,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -11779,6 +12226,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -11791,6 +12249,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -11815,6 +12283,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -14647,6 +15188,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -14667,7 +15209,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie.min.js b/build/player/lottie.min.js index a3919efc7..0202f331c 100644 --- a/build/player/lottie.min.js +++ b/build/player/lottie.min.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6656,6 +6669,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8398,6 +8419,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -10598,13 +10697,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -11125,6 +11243,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -11410,6 +11793,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -11474,6 +11864,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -11757,6 +12148,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -11772,6 +12175,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -11779,6 +12226,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -11791,6 +12249,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -11815,6 +12283,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -14647,6 +15188,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -14667,7 +15209,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_canvas.js b/build/player/lottie_canvas.js index cb91666a8..c71cef832 100644 --- a/build/player/lottie_canvas.js +++ b/build/player/lottie_canvas.js @@ -5870,6 +5870,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6029,6 +6033,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7754,6 +7767,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -9115,6 +9206,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9179,6 +9277,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9462,6 +9561,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9477,6 +9588,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9484,6 +9639,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9496,6 +9662,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9520,6 +9696,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12352,6 +12601,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -12372,7 +12622,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_canvas.min.js b/build/player/lottie_canvas.min.js index cb91666a8..c71cef832 100644 --- a/build/player/lottie_canvas.min.js +++ b/build/player/lottie_canvas.min.js @@ -5870,6 +5870,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6029,6 +6033,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7754,6 +7767,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -9115,6 +9206,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9179,6 +9277,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9462,6 +9561,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9477,6 +9588,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9484,6 +9639,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9496,6 +9662,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9520,6 +9696,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12352,6 +12601,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -12372,7 +12622,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_canvas_worker.js b/build/player/lottie_canvas_worker.js index 79e1827a3..932abe4a6 100644 --- a/build/player/lottie_canvas_worker.js +++ b/build/player/lottie_canvas_worker.js @@ -5754,6 +5754,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -5913,6 +5917,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7681,6 +7694,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -8807,6 +8898,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -8871,6 +8969,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9352,6 +9451,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9367,6 +9478,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9374,6 +9529,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9386,6 +9552,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9410,6 +9586,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12350,7 +12599,7 @@ GroupEffect.prototype.init = function(data,element){ lottiejs.freeze = animationManager.freeze; lottiejs.unfreeze = animationManager.unfreeze; lottiejs.getRegisteredAnimations = animationManager.getRegisteredAnimations; - lottiejs.version = '5.7.0'; + lottiejs.version = '5.7.1a0'; var renderer = ''; return lottiejs; diff --git a/build/player/lottie_canvas_worker.min.js b/build/player/lottie_canvas_worker.min.js index 79e1827a3..932abe4a6 100644 --- a/build/player/lottie_canvas_worker.min.js +++ b/build/player/lottie_canvas_worker.min.js @@ -5754,6 +5754,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -5913,6 +5917,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7681,6 +7694,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -8807,6 +8898,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -8871,6 +8969,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9352,6 +9451,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9367,6 +9478,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9374,6 +9529,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9386,6 +9552,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9410,6 +9586,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12350,7 +12599,7 @@ GroupEffect.prototype.init = function(data,element){ lottiejs.freeze = animationManager.freeze; lottiejs.unfreeze = animationManager.unfreeze; lottiejs.getRegisteredAnimations = animationManager.getRegisteredAnimations; - lottiejs.version = '5.7.0'; + lottiejs.version = '5.7.1a0'; var renderer = ''; return lottiejs; diff --git a/build/player/lottie_html.js b/build/player/lottie_html.js index 8528f831e..f996a4d5f 100644 --- a/build/player/lottie_html.js +++ b/build/player/lottie_html.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6324,6 +6337,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8040,6 +8061,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9341,13 +9440,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -9868,6 +9986,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -10153,6 +10536,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -10217,6 +10607,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -10500,6 +10891,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -10515,6 +10918,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -10522,6 +10969,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -10534,6 +10992,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -10558,6 +11026,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -13390,6 +13931,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -13410,7 +13952,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_html.min.js b/build/player/lottie_html.min.js index 8528f831e..f996a4d5f 100644 --- a/build/player/lottie_html.min.js +++ b/build/player/lottie_html.min.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6324,6 +6337,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8040,6 +8061,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9341,13 +9440,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -9868,6 +9986,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -10153,6 +10536,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -10217,6 +10607,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -10500,6 +10891,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -10515,6 +10918,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -10522,6 +10969,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -10534,6 +10992,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -10558,6 +11026,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -13390,6 +13931,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -13410,7 +13952,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light.js b/build/player/lottie_light.js index 9a048f64a..7eae92e67 100644 --- a/build/player/lottie_light.js +++ b/build/player/lottie_light.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7737,6 +7750,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9071,6 +9162,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9135,6 +9233,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9418,6 +9517,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9433,6 +9544,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9440,6 +9595,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9452,6 +9618,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9476,6 +9652,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -9831,6 +10080,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -9851,7 +10101,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light.min.js b/build/player/lottie_light.min.js index 9a048f64a..7eae92e67 100644 --- a/build/player/lottie_light.min.js +++ b/build/player/lottie_light.min.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7737,6 +7750,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9071,6 +9162,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9135,6 +9233,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9418,6 +9517,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9433,6 +9544,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9440,6 +9595,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9452,6 +9618,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9476,6 +9652,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -9831,6 +10080,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -9851,7 +10101,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light_canvas.js b/build/player/lottie_light_canvas.js index e08128467..f3a50ccc5 100644 --- a/build/player/lottie_light_canvas.js +++ b/build/player/lottie_light_canvas.js @@ -5870,6 +5870,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6029,6 +6033,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7754,6 +7767,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -9115,6 +9206,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9179,6 +9277,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9462,6 +9561,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9477,6 +9588,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9484,6 +9639,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9496,6 +9662,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9520,6 +9696,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -9875,6 +10124,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -9895,7 +10145,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light_canvas.min.js b/build/player/lottie_light_canvas.min.js index e08128467..f3a50ccc5 100644 --- a/build/player/lottie_light_canvas.min.js +++ b/build/player/lottie_light_canvas.min.js @@ -5870,6 +5870,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6029,6 +6033,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7754,6 +7767,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGShapeElement(data,globalData,comp){ //List of drawable elements this.shapes = []; @@ -9115,6 +9206,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9179,6 +9277,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9462,6 +9561,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9477,6 +9588,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9484,6 +9639,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9496,6 +9662,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9520,6 +9696,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -9875,6 +10124,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -9895,7 +10145,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light_html.js b/build/player/lottie_light_html.js index 68073888f..96dd16743 100644 --- a/build/player/lottie_light_html.js +++ b/build/player/lottie_light_html.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6324,6 +6337,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8040,6 +8061,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9341,13 +9440,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -9868,6 +9986,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -10153,6 +10536,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -10217,6 +10607,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -10500,6 +10891,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -10515,6 +10918,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -10522,6 +10969,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -10534,6 +10992,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -10558,6 +11026,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -10913,6 +11454,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -10933,7 +11475,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_light_html.min.js b/build/player/lottie_light_html.min.js index 68073888f..96dd16743 100644 --- a/build/player/lottie_light_html.min.js +++ b/build/player/lottie_light_html.min.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -6324,6 +6337,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; @@ -8040,6 +8061,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9341,13 +9440,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; @@ -9868,6 +9986,271 @@ HImageElement.prototype.createContent = function(){ this.baseElement.setAttribute('id',this.data.ln); } }; +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; + function HCameraElement(data,globalData,comp){ this.initFrame(); this.initBaseData(data,globalData,comp); @@ -10153,6 +10536,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -10217,6 +10607,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -10500,6 +10891,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -10515,6 +10918,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -10522,6 +10969,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -10534,6 +10992,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -10558,6 +11026,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -10913,6 +11454,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -10933,7 +11475,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_svg.js b/build/player/lottie_svg.js index 24b047ffb..256343883 100644 --- a/build/player/lottie_svg.js +++ b/build/player/lottie_svg.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7737,6 +7750,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9071,6 +9162,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9135,6 +9233,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9418,6 +9517,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9433,6 +9544,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9440,6 +9595,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9452,6 +9618,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9476,6 +9652,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12308,6 +12557,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -12328,7 +12578,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/build/player/lottie_svg.min.js b/build/player/lottie_svg.min.js index 24b047ffb..256343883 100644 --- a/build/player/lottie_svg.min.js +++ b/build/player/lottie_svg.min.js @@ -5874,6 +5874,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } @@ -6033,6 +6037,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; @@ -7737,6 +7750,84 @@ ISolidElement.prototype.createContent = function(){ rect.setAttribute('fill',this.data.sc); this.layerElement.appendChild(rect); }; +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; + function SVGCompElement(data,globalData,comp){ this.layers = data.layers; this.supports3d = true; @@ -9071,6 +9162,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -9135,6 +9233,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; @@ -9418,6 +9517,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -9433,6 +9544,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -9440,6 +9595,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -9452,6 +9618,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -9476,6 +9652,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { @@ -12308,6 +12557,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; @@ -12328,7 +12578,7 @@ lottie.freeze = animationManager.freeze; lottie.unfreeze = animationManager.unfreeze; lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations; lottie.__getFactory = getFactory; -lottie.version = '5.7.0'; +lottie.version = '5.7.1a0'; function checkReady() { if (document.readyState === "complete") { diff --git a/package.json b/package.json index 807fa1e02..464bb095b 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "lottie-web", - "version": "5.7.0", + "version": "5.7.1a0", "description": "After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript", "main": "./build/player/lottie.js", "repository": { "type": "git", - "url": "https://github.com/airbnb/lottie-web.git" + "url": "https://github.com/livingbio/lottie-web.git" }, "scripts": { "build": "node tasks/build.js", diff --git a/player/index.html b/player/index.html index a693b5dd2..82095d9cb 100644 --- a/player/index.html +++ b/player/index.html @@ -9,12 +9,20 @@ height: 100%; overflow-x: hidden; overflow-y: auto; + + /*-webkit-perspective: 1000;*/ + /*-webkit-filter: blur(0);*/ + /*-webkit-font-smoothing: subpixel-antialiased;*/ + + /*-webkit-transform: translateZ(0);*/ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } #lottie{ - background-color:#ccc; - width:100%; - height:100%; + background-color:#fff; + width:100% !important; + height:100% !important; display:block; overflow: hidden; transform: translate3d(0,0,0); @@ -101,6 +109,7 @@ + @@ -131,6 +140,8 @@ + + @@ -160,9 +171,6 @@ - - -
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js index 78a005334..a711b5108 100644 --- a/player/js/animation/AnimationItem.js +++ b/player/js/animation/AnimationItem.js @@ -269,6 +269,18 @@ AnimationItem.prototype.gotoFrame = function () { if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){ this.currentFrame = this.timeCompleted; } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + // find the relative time of the video (in the current layer) + var goToTime = (this.currentFrame - layer.st) / (this.frameModifier * 1000); + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', goToTime); + } + } + this.trigger('enterFrame'); this.renderFrame(); }; @@ -284,6 +296,50 @@ AnimationItem.prototype.renderFrame = function () { } }; +AnimationItem.prototype.playAudioVideo = function (element, action, goToTime) { + var videoCount = element.getElementsByTagName('video').length; + var audioCount = element.getElementsByTagName('audio').length; + var v, a; + + switch (action) { + case 'play': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].play(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].play(); + } + break; + case 'pause': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].pause(); + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].pause(); + } + break; + case 'goToTime': + for (v = 0; v < videoCount; v++) { + element.getElementsByTagName('video')[v].currentTime = goToTime; + } + for (a = 0; a < audioCount; a++) { + element.getElementsByTagName('audio')[a].currentTime = goToTime; + } + break; + } +} + +AnimationItem.prototype.layerIsStarted = function (layer) { + // ip = start time all video by FPS + // st = start specific time by FPS + // op = end time all video by FPS + if (layer.st <= this.currentRawFrame && this.currentRawFrame < layer.op) { + return true; + } else { + return false; + } +} + AnimationItem.prototype.play = function (name) { if(name && this.name != name){ return; @@ -291,6 +347,17 @@ AnimationItem.prototype.play = function (name) { if(this.isPaused === true){ this.isPaused = false; if(this._idle){ + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + if (this.isPaused === false) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'play', null); + } + } + } + this._idle = false; this.trigger('_active'); } @@ -303,6 +370,16 @@ AnimationItem.prototype.pause = function (name) { } if(this.isPaused === false){ this.isPaused = true; + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if (this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'pause', null); + } + } + this._idle = true; this.trigger('_idle'); } @@ -327,6 +404,79 @@ AnimationItem.prototype.stop = function (name) { this.playCount = 0; this._completedLoop = false; this.setCurrentRawFrameValue(0); + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + if(this.layerIsStarted(layer)) { + this.playAudioVideo(this.renderer.layerElement.children[i], 'goToTime', 0); + } + } +}; + +// mute function +AnimationItem.prototype.mute = function (name) { + if(name && this.name != name){ + return; + } + + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if (this.layerIsStarted(layer)) { + if (this.isMute === false || this.isMute == null) { + this.adjustAudio(this.renderer.elements, 'mute', false, null); + this.isMute = true; + break; + } + // TODO: CHECK with two audio's playing together + else if (this.isMute === true) { + this.adjustAudio(this.renderer.elements, 'mute', true, null); + this.isMute = false; + break; + } + } + } +}; + +AnimationItem.prototype.adjustAudio = function (elements, action, mute, volume) { + + if (elements instanceof Array) { + for (i = 0; i < elements.length; i++) { + if (elements[i].baseElement.getElementsByTagName('audio').length != 0) { + if (action == 'mute') { + if (mute === false) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = true; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 0; + } + + else if (mute === true) { + elements[i].baseElement.getElementsByTagName('audio')[0].muted = false; + elements[i].baseElement.getElementsByTagName('audio')[0].volume = 1; + } + } else if (action == 'setVolume') { + elements[i].baseElement.getElementsByTagName('audio')[0].volume = volume; + } + + } + } + } +} + +// set volume function 0-1 (decimal option) +AnimationItem.prototype.setVolumeRange = function (value) { + var i, len = this.renderer.layers.length, layer; + + for (i = len - 1; i >= 0; i--) { + layer = this.renderer.layers[i]; + + if(this.layerIsStarted(layer)) { + this.adjustAudio(this.renderer.elements, 'setVolume', true, value); + } + } }; AnimationItem.prototype.goToAndStop = function (value, isFrame, name) { diff --git a/player/js/animation/AnimationManager.js b/player/js/animation/AnimationManager.js index 23c0084ac..9082214e2 100644 --- a/player/js/animation/AnimationManager.js +++ b/player/js/animation/AnimationManager.js @@ -141,6 +141,13 @@ var animationManager = (function(){ } } + function mute(animation) { + var i; + for(i=0;i=0;i-=1){ @@ -205,6 +212,7 @@ var animationManager = (function(){ moduleOb.play = play; moduleOb.pause = pause; moduleOb.stop = stop; + moduleOb.mute = mute; moduleOb.togglePause = togglePause; moduleOb.searchAnimations = searchAnimations; moduleOb.resize = resize; diff --git a/player/js/elements/VideoElement.js b/player/js/elements/VideoElement.js new file mode 100644 index 000000000..8a91bb11f --- /dev/null +++ b/player/js/elements/VideoElement.js @@ -0,0 +1,77 @@ +function IVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); + this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h}; +} + +extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IVideoElement); + +IVideoElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + this.innerElem = createNS('foreignObject'); + this.innerElem.setAttribute('width',this.assetData.w+"px"); + this.innerElem.setAttribute('height',this.assetData.h+"px"); + this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio); + + var videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + videoElem.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + videoElem.setAttribute('preload',''); + videoElem.setAttribute('loop','loop'); + videoElem.setAttribute('playsinline',''); //for iphone support + videoElem.setAttribute('width',this.assetData.w); + videoElem.setAttribute('height',this.assetData.h); + videoElem.setAttribute('style','object-fit: fill'); + this.innerElem.appendChild(videoElem); + + var sourceElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + sourceElem.setAttribute('src',assetPath); + if (this.data.cl) { + sourceElem.setAttribute('type','video/'+this.data.cl); + } + videoElem.appendChild(sourceElem); + + // this.maskedElement = this.innerElem.parentElement; + this.layerElement.appendChild(this.innerElem); +}; + +IVideoElement.prototype.hide = function(){ + if (!this.hidden && (!this.isInRange || this.isTransparent)) { + var elem = this.baseElement || this.layerElement; + + if (elem.getElementsByTagName('video').length != 0) { + elem.getElementsByTagName('video')[0].pause(); + elem.getElementsByTagName('video')[0].currentTime = 0; + } + + elem.style.display = 'none'; + this.hidden = true; + } +}; + +IVideoElement.prototype.show = function() { + if (this.isInRange && !this.isTransparent){ + if (!this.data.hd) { + var elem = this.baseElement || this.layerElement; + + if (elem.parentElement.parentElement.getElementsByTagName('g').item(0) != undefined){ + if(elem.getElementsByTagName('video').length !=0) { + elem.getElementsByTagName('video').item(0).setAttribute('style',elem.parentElement.parentElement.getAttribute("style")); + } + } + + if(elem.getElementsByTagName('video').length !=0 && elem.getElementsByTagName('video')[0].currentTime == 0) { + elem.getElementsByTagName('video')[0].play(); + } + + elem.style.display = 'block'; + } + this.hidden = false; + this._isFirstFrame = true; + } +}; + +IVideoElement.prototype.sourceRectAtTime = function() { + return this.sourceRect; +}; diff --git a/player/js/elements/htmlElements/HAudioElement.js b/player/js/elements/htmlElements/HAudioElement.js new file mode 100644 index 000000000..7fdbbd85f --- /dev/null +++ b/player/js/elements/htmlElements/HAudioElement.js @@ -0,0 +1,78 @@ +function HAudioElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HAudioElement); + +HAudioElement.prototype.createContent = function(){ + + var assetPath = this.globalData.getAssetsPath(this.assetData); + + var parent = document.createElement('div'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','audio'); + styleDiv(cont); + + cont.setAttribute('preload',''); + cont.setAttribute('playsinline',''); + parent.appendChild(cont); + + this.audioElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.audioElem.setAttribute('src',assetPath); + cont.appendChild(this.audioElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + this.checkParenting(); +}; + + + +HAudioElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset audio position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('audio').length !=0){ + this.baseElement.getElementsByTagName('audio')[0].pause(); + this.baseElement.getElementsByTagName('audio')[0].currentTime = 0; + + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + +HAudioElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + //play the video + if(this.comp.comp.animationItem.isPaused === false) { + if(this.baseElement.getElementsByTagName('audio').length !=0){ + if (this.baseElement.getElementsByTagName('audio')[0].paused) { + this.baseElement.getElementsByTagName('audio')[0].play(); + } + } + } + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + + this.firstFrame = false; + } +}; + +HAudioElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; diff --git a/player/js/elements/htmlElements/HCompElement.js b/player/js/elements/htmlElements/HCompElement.js index a98983735..48655b5c9 100644 --- a/player/js/elements/htmlElements/HCompElement.js +++ b/player/js/elements/htmlElements/HCompElement.js @@ -8,13 +8,32 @@ function HCompElement(data,globalData,comp){ this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; } +// var isvideo = false + +// function checkVideoLayer(layers){ +// if (layers) { +// for (var i = layers.length - 1; i >= 0; i--) { +// if (layers[i].layers != undefined){ +// checkVideoLayer(layers[i].layers) +// } + +// if(layers[i].ty == 9) { +// isvideo = true; +// } +// }} +// } + extendPrototype([HybridRenderer, ICompElement, HBaseElement], HCompElement); HCompElement.prototype._createBaseContainerElements = HCompElement.prototype.createContainerElements; HCompElement.prototype.createContainerElements = function(){ this._createBaseContainerElements(); //divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)'; - if(this.data.hasMask){ + if (this.data.hasMask) { + // isvideo = false + // checkVideoLayer(this.data.layers) + // if (isvideo != true && this.data.layers[0].ty != 9) {} else {} + this.svgElement.setAttribute('width',this.data.w); this.svgElement.setAttribute('height',this.data.h); this.transformedElement = this.baseElement; diff --git a/player/js/elements/htmlElements/HVideoElement.js b/player/js/elements/htmlElements/HVideoElement.js new file mode 100644 index 000000000..c778c02db --- /dev/null +++ b/player/js/elements/htmlElements/HVideoElement.js @@ -0,0 +1,186 @@ +function HVideoElement(data,globalData,comp){ + this.assetData = globalData.getAssetData(data.refId); + this.initElement(data,globalData,comp); +} + +extendPrototype([BaseElement,TransformElement,HBaseElement,HSolidElement,HierarchyElement,FrameElement,RenderableElement], HVideoElement); + +HVideoElement.prototype.createContent = function(){ + // this.isMasked = this.checkMasks(); + var assetPath = this.globalData.getAssetsPath(this.assetData); + + // console.log(this.data); + if(this.data.hasMask){ + //need to add mask support + var parent = document.createElement('div'); + + // styleDiv(parent); + // var cont = createNS('svg'); + // styleDiv(cont); + // cont.setAttribute('width',this.assetData.w); + // cont.setAttribute('height',this.assetData.h); + // parent.appendChild(cont); + // this.imageElem = createNS('image'); + // this.imageElem.setAttribute('width',this.assetData.w+"px"); + // this.imageElem.setAttribute('height',this.assetData.h+"px"); + // this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath); + // cont.appendChild(this.imageElem); + // this.layerElement = parent; + // this.transformedElement = parent; + // this.baseElement = parent; + // this.innerElem = parent; + // this.maskedElement = this.imageElem; + // + + // console.log('ffffff'); + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + + parent.appendChild(cont); + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.maskedElement = cont; + + this.renderType = 'html'; + } else { + + // var parent = document.createElement('foreignObject'); + // // x="10" y="10" + // parent.setAttribute('x','10'); + // parent.setAttribute('y','10'); + // + // parent.setAttribute('width','1000'); + // parent.setAttribute('height','1000'); + // + // + // var cont_vid = document.createElementNS('http://www.w3.org/1999/xhtml','body'); + // cont_vid.setAttribute('xmlns','http://www.w3.org/1999/xhtml'); + + if(this.parentContainer.parentNode != undefined) { + if (this.parentContainer.parentNode.nodeName == 'svg') { + var parent = createNS('foreignObject'); + parent.setAttribute('width',this.assetData.w+"px"); + parent.setAttribute('height',this.assetData.h+"px"); + } + } + else + { + var parent = document.createElement('div'); + + + } + + styleDiv(parent); + + var cont = document.createElementNS('http://www.w3.org/1999/xhtml','video'); + styleDiv(cont); + + cont.setAttribute('muted',''); //iphone suuport - we need to mute audio to allow play/stop video from js + cont.setAttribute('preload',''); + cont.setAttribute('loop','loop'); + cont.setAttribute('playsinline',''); //for iphone support + cont.setAttribute('width',this.assetData.w); + cont.setAttribute('height',this.assetData.h); + cont.setAttribute('style','object-fit: fill'); + + // console.log(this.parentContainer.attributes); + if (this.parentContainer.getElementsByTagName('g').item(0) != undefined){ + if (this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0) != undefined) { + cont.setAttribute('style', 'clip-path:' + this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent); + } + } + + if (this.parentContainer.attributes.getNamedItem('clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('clip-path').textContent); + + if (this.parentContainer.attributes.getNamedItem('data-clip-path') != undefined) + cont.setAttribute('style','-webkit-mask:'+this.parentContainer.attributes.getNamedItem('data-clip-path').textContent); + + // if (this.parentContainer.attributes.item(0) != undefined) + // cont.setAttribute('style','clip-path:'+this.parentContainer.attributes.item(0).textContent); + + + + + + parent.appendChild(cont); + + + this.videoElem = document.createElementNS('http://www.w3.org/1999/xhtml','source'); + this.videoElem.setAttribute('src',assetPath); + cont.appendChild(this.videoElem); + this.layerElement = parent; + this.transformedElement = parent; + this.baseElement = parent; + this.innerElem = parent; + this.renderType = 'html'; + + // console.log(this.baseElement); + + // console.log(this.parentContainer.parentElement.getElementsByTagName('g').item(0).attributes.item(0).textContent) + // console.log(this.parentContainer.getElementsByTagName('g').item(0).attributes.item(0).textContent) + + + + } + + this.checkParenting(); +}; + +HVideoElement.prototype.hide = function(){ + if(!this.hidden){ + //we need to pause & reset video position in case we play this video again (like in loop) + if(this.baseElement.getElementsByTagName('video').length !=0) { + this.baseElement.getElementsByTagName('video')[0].pause(); + this.baseElement.getElementsByTagName('video')[0].currentTime = 0; + } + + this.layerElement.style.display = 'none'; + this.hidden = true; + } +}; + + +HVideoElement.prototype.renderFrame = function(parentMatrix){ + var renderParent = this._parent.renderFrame.call(this,parentMatrix); + if(renderParent===false){ + this.hide(); + return; + } + + if(this.hidden){ + + + if(this.baseElement.getElementsByTagName('video').length !=0 && this.baseElement.getElementsByTagName('video')[0].currentTime == 0) { + this.baseElement.getElementsByTagName('video')[0].play(); + } + + this.hidden = false; + this.layerElement.style.display = 'block'; + } + if(this.firstFrame){ + this.firstFrame = false; + } +}; + +HVideoElement.prototype.destroy = function(){ + this._parent.destroy.call(); + this.innerElem = null; +}; \ No newline at end of file diff --git a/player/js/module.js b/player/js/module.js index d2ce1e837..07013cf73 100644 --- a/player/js/module.js +++ b/player/js/module.js @@ -73,6 +73,7 @@ function getFactory(name) { lottie.play = animationManager.play; lottie.pause = animationManager.pause; +lottie.mute = animationManager.mute; lottie.setLocationHref = setLocationHref; lottie.togglePause = animationManager.togglePause; lottie.setSpeed = animationManager.setSpeed; diff --git a/player/js/renderers/BaseRenderer.js b/player/js/renderers/BaseRenderer.js index 17b6fb87d..c1825c214 100644 --- a/player/js/renderers/BaseRenderer.js +++ b/player/js/renderers/BaseRenderer.js @@ -29,6 +29,10 @@ BaseRenderer.prototype.createItem = function(layer){ return this.createShape(layer); case 5: return this.createText(layer); + case 6: + return this.createAudio(layer); + case 9: + return this.createVideo(layer); case 13: return this.createCamera(layer); } diff --git a/player/js/renderers/HybridRenderer.js b/player/js/renderers/HybridRenderer.js index fe66ed053..578dfbf14 100644 --- a/player/js/renderers/HybridRenderer.js +++ b/player/js/renderers/HybridRenderer.js @@ -89,6 +89,14 @@ HybridRenderer.prototype.createText = function (data) { return new HTextElement(data, this.globalData, this); }; +HybridRenderer.prototype.createVideo = function (data) { + return new HVideoElement(data,this.globalData,this); +}; + +HybridRenderer.prototype.createAudio = function (data) { + return new HAudioElement(data,this.globalData,this); +}; + HybridRenderer.prototype.createCamera = function (data) { this.camera = new HCameraElement(data, this.globalData, this); return this.camera; diff --git a/player/js/renderers/SVGRenderer.js b/player/js/renderers/SVGRenderer.js index 9c672abbe..fdd3f7743 100644 --- a/player/js/renderers/SVGRenderer.js +++ b/player/js/renderers/SVGRenderer.js @@ -61,6 +61,15 @@ function SVGRenderer(animationItem, config){ extendPrototype([BaseRenderer],SVGRenderer); +SVGRenderer.prototype.createAudio = function (data) { + throw new Error('You\'re using a audio object. Try the html renderer.'); +}; + +SVGRenderer.prototype.createVideo = function (data) { +// throw new Error('You\'re using a video object. Try the html renderer.'); + return new IVideoElement(data,this.globalData,this); +}; + SVGRenderer.prototype.createNull = function (data) { return new NullElement(data,this.globalData,this); }; diff --git a/tasks/build.js b/tasks/build.js index dc48c5992..5ce59659b 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -3,7 +3,7 @@ const cheerio = require('cheerio'); const UglifyJS = require("uglify-js"); const rootFolder = 'player/'; -const bm_version = '5.7.0'; +const bm_version = '5.7.1a0'; const buildReducedVersion = process.argv[2] === 'reduced' const defaultBuilds = ['full', 'svg_light', 'svg', 'canvas', 'html', 'canvas_light', 'html_light', 'canvas_worker'] @@ -324,6 +324,10 @@ const scripts = [ src: 'js/elements/SolidElement.js', builds: defaultBuilds }, + { + src: 'js/elements/VideoElement.js', + builds: defaultBuilds + }, { src: 'js/elements/svgElements/SVGCompElement.js', builds: ['full', 'svg', 'svg_light', 'html', 'html_light'] @@ -436,6 +440,14 @@ const scripts = [ src: 'js/elements/htmlElements/HImageElement.js', builds: ['full', 'html', 'html_light'] }, + { + src: 'js/elements/htmlElements/HVideoElement.js', + builds: ['full','html','html_light'] + }, + { + src: 'js/elements/htmlElements/HAudioElement.js', + builds: ['full','html','html_light'] + }, { src: 'js/elements/htmlElements/HCameraElement.js', builds: ['full', 'html', 'html_light']