TimelineLite Javascript animation issues when replaying a slide

May 11, 2021

So, I've been experimenting with using javascript and TimelineLite to loop animations in storyline (edit: on just a single slide. I am not trying to loop an animation across several slides). But I've run into this problem. Below is an example of the animation looping, the crown just scales up and down:

Looping animation

Here is the kicker though. When I replay the slide in storyline, the image seems to get added to a new timelinelite instance, while still being apart of the old timelinelite. So the image kind of ovelaps the animations and goes all screwy:
Animation woes

I'm real sure why the image is holding onto the old animation. I want to avoid setting up variables in storyline that could be used to only make the javascript run once, because if I start to use this technique on multiple pages, it starts to get messy with having a variable for each page.

I've also tried adding a custom class to the image. Basically, I grab the <div> element that the image is contained in and add a class to it when I start the animation. And then the idea was check to see if that custom class was present before executing the javascript again. But alas, when you replay the slide, it reloads the <div> from the default state and removes the custom class I created.

So now I am at a loss. I'm not sure what function the replay slide is calling in order for me to see what is exactly happening so that I can begin to track down a different solution. Has anyone else who makes their own custom animations been able to solve for this? I've looked around on the forums and I've not seen a mention of it.

 

This is the code I currently have for looping the animation:

var iconObject = document.querySelectorAll("[data-acc-text='crown.png']");

var tl = new TimelineLite({onComplete:function() {
this.restart()}
});
tl.to(iconObject, 1, {scale: '+=0.10', ease: "power1.inOut", overwrite:"none"});
tl.to(iconObject, 1, {scale: '-=0.10', ease: "power1.inOut", overwrite:"none"});
13 Replies
Math Notermans

I work a lot with GSAP and didnot encounter this yet. As Storyline 360 standard has  a version of GSAP 3 built in, you probably dont have to use Timelinelite anymore but can use GSAP 3 syntax...
Something like this...

var iconObject = document.querySelector("[data-acc-text='crown.png']");

var tl = gsap.timeline({repeat: -1, onComplete: doSomething});
tl.to(iconObject, 1, {scale: '+=0.10', ease: "power1.inOut",});
tl.to(iconObject, 1, {scale: '-=0.10', ease: "power1.inOut"});

function doSomething(){

console.log("doSomething onComplete");

}

It might have to do with scope of code inside Storyline. Every trigger, every slide...everything in Storyline has its own scope. So if you set a variable or timeline at a slide...the next slide doesnot know about it. Only way to make sure you can target some variables is defining them somewhere globally. That would be either in the player or at some spot in the HTML code.

I do that constantly. I have a generic_functions.js file i load at start of a Storyline. Inthere i have a lot of generic functions that i can call anytime... on any slide. Also some arrays and variables set in that js-file in which i can save some needed values.

Do hope this helps you.

Kind regards,
Math

 

Math Notermans

i did test it in Storyline 360 and works as intended. Except for a small stutter in the repeating timeline of the crown..but thats to expect because on the next slide the timeline is a new one and starts over...so building repeating elements that play flawless over multiple slides is something completely different. Offcourse it can be done...but needs quite some more tips and tricks.

Here is my sample

PS. if you are using Storyline 3, you need to add the latest version of GSAP as in SL3 its not included.

Math Notermans

Do share your project Chris... as i now see..im going to a second slide and not replaying the current slide...im quite sure it can be solved.

Published my version in 360 on Review with the Classic Player as you have it...with the replay icon on the progressbar.. and with my code in Storyline 360 it works perfectly.

https://360.articulate.com/review/content/7be679e8-6188-4867-b486-d858e3982f55/review

I do think the 'overwrite' in your tween is unnecessary and might cause the issues.

As you can see in my sample... the relative scale you use "scale: '+=0.10'" will cause the crown to grow and keep getting bigger...if you interrupt the tween by clicking replay. Im quite sure that can be solved too... but not in scope for me now ;-)

Chris Curry

Hey Math,

Thanks for the replies. I'm not sure if I communicated my issue fully because the issue I'm trying to avoid is actually present in your AR360 review link.

On your looping animation, if you hit the replay button several times (or wait until the crown is at its largest and hit replay) you will see the issue. The animation replays on that crown. So, if you hit replay when the crown is at its largest, it will stay at that size, and then start the animation and grow more. And that will continue infinitely. Eventually, if you hit replay enough time, I suspect you will crash the browser because it is trying to play too many animations.

I want to stop that issue from happening. I don't necessarily want the animation to loop across multiple pages, I just want to stop it from potentially crashing the browser, or breaking the animation if a user decides to replay the slide from the beginning.

Thanks,

Curry

Chris Curry

Ah, ok, I misunderstood. I'll give that a shot. But I am still concerned that the animation will continue to trigger several times potentially causing a browser crash. 

I put a console.log in the loop that just displayed a number and counted up after each loop. And when I hit replay on the slide, I could see the console.log jumping by 2's and 3's and 4's (directly related to the amount of replays I did). Have you seen this issue as well?

Math Notermans

Yeah, i do think its because of the way Storyline implements its timeline. Basically Storyline's timeline is a GSAP timeline. If we could only hack that internally, that would be way better.

You might consider forgetting about Storyline's timeline. I mostly do. Building interactions in Storyline without using the timeline and layers i prefer. Never any problems..and with GSAP build in into SL360 im good.

Manny Rak

Hi, I'm fairly new to Storyline 360 and did some research before I found you are the expert in GSAP. I wanted to ask if you don't mind. I have a gsap element animating after a while in the timeline and I noticed that when I click on the rewind button on if I use the seek function, once the animation is done, it won't restart. Instead it will just jump between the before and after state.

Any clues on how to make the animation play again if I hit the rewind/replay button? 

 

Thanks in advance. Below is the current code I have.

    var elemanim_1 = document.querySelector("[data-acc-text='bg_circle']");
    var tl = gsap.timeline();
    tl.to(elemanim_1, {x: "85%", y: "32%", duration: 0.5 ,scale:1.6});

Math Notermans

First of all..share a sample...as it makes it a lot easier to debug.

Storyline's rewind, seek and timeline controls are totally unaware of any Javascript GSAP code you add. I seldom use Storyline's own controls but create my own, so i have full control. Most of my projects use the transparant player. So no player at all :-)

If you want your GSAP animations to respond to Storyline's timeline controls... well you have to add triggers that reset your animations as needed when clicking the controls in question.

Manny Rak

Thanks for your answer and sorry for the delay. Attached is a sample file with the 2 elements I scale by using GSAP. if you notice when publishing it and playing it on the browser, the first time, the 2 shape will scale normally. When i press the play button again though, the animation will no longer be smooth, it will just jump from the original size to the final size. As you mention that i should add some triggers to reset the animation, any chance to be more specific. I'm so new to articulate that there's a lot I don't understand and haven't explored just yet.

Again thank you very much for you advice and time

Math Notermans

Hi Manny, As mentioned earlier...Storyline's timeline play/pause button is totally unaware of any GSAP based animation. It is possible to select it and make a GSAP animation act upon clicking Storyline's player controls, however that takes quite a deep knowledge of both Storyline's player and Javascript.

I do suspect you don't have both, so i would suggest skip the GSAP and Javascript stuff and learn Storyline first. You can get this done in Storyline without using GSAP javascript. When at time you know Storyline well enough... and you encounter things you cannot do by default in Storyline... then learn Javascript and GSAP and you can tackle it.

That said, i probably make some samples of how to get control of the Storyline player to control GSAP... when i got some time... 

Manny Rak

Thank you very much for take the time to answer, I really appreciate it. Yeah, I'm definitely learning Storyline and trying to go in depth wwith it to understand all its little intricacies. For this specific problem, I went the GSAP way because I couldn't find a proper way to scale and move those objects at a certain time. I'm so used to video editing so I thought there would be something like keyframes or something like that.