Forum Discussion
Storyline360, Animation and GSAP ( Greensock )
Hi,
Trying to figure something out in SL360 i stumbled upon the ds-bootstrap.min.js file thats added to the lib/scripts folder when publishing a Storyline360 file. In that file are GSAP(Greensock) references... some samples../*!
* VERSION: 1.11.8
* DATE: 2014-05-13
* UPDATES AND DOCS AT: http://www.greensock.com
*
* @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
* This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
* Club GreenSock members, the software agreement that was issued with your membership.
*
* @author: Jack Doyle, jack@greensock.com
*/
What i can find in that file that both GSAP CSS-plugin, easing and basic GSAP tweens are somehow used in Storyline.
Bad news however is that its a really old version they have implemented... from 2014... version 1.11.8, whereas the current GSAP version is version 3.5.1 !!!
Big advantages of the newer GSAP are mobile performance, speed and perfect control over SVG. So Storyline would certainly benefit from updating their internal used Storyline to the latest version.
As Storyline probably uses GSAP for all its animation features, the transitions and everything, i personally would really like it to have the control of GSAP in the hands of the frontend-user. I do use GSAP constantly in my elearning projects, but always have to add the newest version..
Is there an option to get the latest version of GSAP implemented in Storyline?
And can we have some better scripted control over Storyline elements...as you do use it already anyway?
Kind regards,
Math Notermans
- zhongyuwuCommunity Member
How can I change the image with another? Say I can access the image by the code:
var myElement = document.querySelectorAll("[data-acc-text='4.jpg']");
Not sure how can I replace it with another image.
- MathNotermans-9Community Member
Yeah it is possible. You need to get to the source of an element and replace that then with any new source. Biggest issue is however that you have to have it already inside your Storyline...or have both the original and the new image outside Storyline.
- zhongyuwuCommunity Member
yeah... I am having a hard time locating the source of the element...the alternative way I am thinking to destroy the current image and add a new image on the placeholder of the destroyed image. I wanted to dynamically change the images so it can save a lot of time when creating a course without copy and paste all the images over to a similar course.
- MathNotermans-9Community Member
That is the tough part indeed...getting to the source of the element. Using your inspector you can figure out how to get to it from a given selector.
- MathNotermans-9Community Member
i basically have a function that gets everything from Storyline on start.
getElementsFromStoryline( );
The function gets several preset values that cannot be get by selectors. Most of them are always the same in Storyline. Shapes, buttons, images... As all images are treated as SVG in Storyline and thus have a 'path' element all of them are put in a shapesCollection ( is a WebCollection ).
That i loop get the 'data-text-attribute' and detect the type, text or image.. and treat them differently.
var elText = el.getAttribute('data-acc-text');
When i detect its a image, i get the source's name and can replace it if i want.
if(elText.indexOf(".png")!=-1 || elText.indexOf(".jpg")!=-1 )// if the source is png or jpg...
{
imagesArray.push(i);
console.log("imagesArray: "+i+" / url: "+el.getElementsByTagName('image')[0].getAttribute('xlink:href'));
}
As said its tough...but it works. In my projects i have all my assets... images, shapes, SVG, paths, texts, buttons and UI-elements available to change/script with Javascript.
Making this function work properly cost my about 180 manhours work of my spare time so you know you have a tough road ahead trying this.- zhongyuwuCommunity Member
Thank you very much for the help! Math! I was able to change a single image for now with only the first slide. Going on a tough road is painful, but it is one of the best ways to learn. In this era, everyone wants more automation in the work to make it easier to implement. Nothing feels better to get the code working. Again thank you for your guidance and it really helps me a lot.
- PhilMayorSuper Hero
:-)
- AdrianMurray-caCommunity Member
Hi Math and all,
Having some real problems with GS code. Essentially, I am using the below code to open up more advanced animated sequences but the problem is that sometimes they work, sometimes they don't. The other issue is the moment you re-size the browser, it all just falls apart. Do you have any thoughts please:
//Reference the object
var elderflowerCTA = document.querySelectorAll("[data-acc-text='elderflowerCTA']");
//Animate in GSAP
gsap.set(elderflowerCTA, { scale: 1.05, ease:"bounce.out" });Really frustrating as when the JS executes, the animations look fantastic but they are just so unreliable.
Hope you can help folks. Cheers.
- MathNotermans-9Community Member
First of all, its for sure not GS code thats unreliable as its one the best engines there is and they are very helpfull on their own forum. Its probably due to either mistakes in your own code or due to Storyline's own way of interpreting it.
The resizing browser issue is due to the Modern Storyline player that scales up everything. You can fix that by calculating positions and animations. Quite some approaches for that allover the forum. The Classic player doesnot have that issue.
Do share a sample, as finding errors without it is just guessing.
One guess is the use of querySelectorAll when in fact selecting just a single element. querySelector is better in that case. Another one is using a 'bounce' ease when you use gsap.set... any ease needs time to execute properly. So gsap.to is better in this case.
Kind regards,
Math
- larryvanwave-ffCommunity Member
I purchased Club Greensock, and I have not been able to successfully get SplitText plugin to work. Any idea what I am missing here:
================ code ==============
//name the vars of elements on the slide
var txt1 = document.querySelectorAll("[data-acc-text='text1']");
//load in the plugins
dynamicallyLoadScripts([
"https://(our server site is here)/greensock/minified/SplitText.min.js",
], onLoadScripts);
function onLoadScripts() {
split = new SplitText(txt1, {type:"chars"})
animation.from(split.chars, {opacity:0, y:50, ease:"back(4)", stagger:{
from:"end", //try "center" and "edges"
each:0.05
}})
}
//the function that look for and loads the urls
function dynamicallyLoadScripts(urls, onComplete) {
if (typeof urls === "string") {
urls = [urls];
}
let toLoad = urls.length;
urls.forEach(function(url) {
let script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
script.addEventListener("load", function() {
if (!--toLoad) {
onComplete && onComplete();
}
})
});
}- Jürgen_Schoene_Community Member
SplitText only works for normal DOM text, not for SVG text <tspan> (which is used by storyline for text)
https://greensock.com/forums/topic/12165-splittext-with-svg-text-element-problems/
(Posted August 6, 2015 - I do not believe that anything has changed)
- PhilMayorSuper Hero
Jurgen would it work with the accessible text which is not meant to be SVG based
Sent from my iPhone
- MathNotermans-9Community Member
As a reply on how to use DOM related plugins like GSAP's SplitText and ScrambleText on SVG text in Storyline i made a sample.
https://360.articulate.com/review/content/670bb432-b866-436b-8c1b-1b37d824dd0c/review
I use the lines of code as shown to Phil to grab the texts from all textfields in Storyline ( including buttons )...Determine which one i want to use ( in this case that is i1 ) Then i add a pure HTML text field to Storyline by appending it to a shape onscreen. And that textfield i can then target with GSAPs SplitText or ScrambleText.
Some weirdness with the missing i in textfield. Not sure where that comes from... but this is basically the setup you need to get this working.- PhilMayorSuper Hero
Thanks Math for the help, I am sure this will work
Sent from my iPhone
- larryvanwave-ffCommunity Member
I am wondering why I can get ScrambleTextPlugin to work, does it use a normal DOM text or a SVG text <tspan>?
- Jürgen_Schoene_Community Member
my assumption
- SplitText tries to read the text from the DOM -> nothing found, all text is in <tspan>
- ScrampleText creates with Javascript the text as DOM text and then animated it
- larryvanwave-ffCommunity Member
I really like this feature and was hoping that it would work. Thank you for sharing your knowledge and expertise!
- MathNotermans-9Community Member
All Storyline text adds extra <spans> and is SVG, thus its hard to get pure HTML related things to work.
Do try add a textelement with code and you will see it works on those. - larryvanwave-ffCommunity Member
Thank you Math for the information and example, it looks like the SplitText is working when you use this method. You highlighted the steps, and I am going to see if I can get it to work for me. Your amazing!
- MathNotermans-9Community Member
To help you get started....
This is my function that does the work.function docLoaded_inSL(){
const collection = document.getElementsByClassName("vector-text-item");
const textsArray = [];
let baseStr;
for(var i = 0; i < collection.length;i++){
var sStr = player.GetVar("debugStr");
var someStr = gsap.getProperty(collection[i], "textContent");
var someNewStr = sStr+"<BR>"+"i "+i+": "+someStr;
player.SetVar("debugStr",someNewStr);
textsArray.push(gsap.getProperty(collection[i], "textContent"));
}
const h1 = document.createElement("H1");
const textNode = document.createTextNode(gsap.getProperty(collection[1], "textContent"));
h1.appendChild(textNode);
document.querySelector("[data-acc-text='canvasShape']").appendChild(h1);
var tl = gsap.timeline(),
mySplitText = new SplitText("H1", { type: "words,chars" }),
chars = mySplitText.chars; //an array of all the divs that wrap each character
gsap.set("H1", { perspective: 400 });
tl.from(chars, {
duration: 0.8,
opacity: 0,
scale: 0,
y: 80,
rotationX: 180,
transformOrigin: "0% 50% -50",
ease: "back",
stagger: 0.01
});
}
Basically it gets all texts from Storyline, and then i use one of them to create a HTML textfield to be targeted by SplitText.
Offcourse you can simplify it.
For example by creating a function to create HTML Text elements.function createHTMLText(_string,_targetAccName,_elName){
const h1 = document.createElement(_elName);
const textNode = document.createTextNode(_string);
h1.appendChild(textNode);
document.querySelector("[data-acc-text='"+_targetAccName+"']").appendChild(h1);
}
You can then call that like this...createHTMLText(gsap.getProperty(collection[1], "textContent"),"canvasShape","H1");
or if you donot want to use an existing Storyline textfield, just like this...
createHTMLText("Text to be animated by SplitText","myShape","H1");
And the SplitText functionality you also can put in a function.function createSplitTextAni(_elName){
var tl = gsap.timeline(),
mySplitText = new SplitText(_elName, { type: "words,chars" }),
chars = mySplitText.chars; //an array of all the divs that wrap each character
gsap.set(_elName, { perspective: 400 });
tl.from(chars, {
duration: 0.8,
opacity: 0,
scale: 0,
y: 80,
rotationX: 180,
transformOrigin: "0% 50% -50",
ease: "back",
stagger: 0.01
});
}
So now this cleaned up code will work.let mySplitString = "Bladibla vanillevla and some more text to test this";
createHTMLText(mySplitString,"accNameOfSomeShape","H1");
createSplitTextAni("H1");
function createHTMLText(_string,_targetAccName,_elName){
const newElement = document.createElement(_elName);
const textNode = document.createTextNode(_string);
newElement.appendChild(textNode);
document.querySelector("[data-acc-text='"+_targetAccName+"']").appendChild(newElement);
}
function createSplitTextAni(_elName){
var tl = gsap.timeline(),
mySplitText = new SplitText(_elName, { type: "words, chars" }),
chars = mySplitText.chars; //an array of all the divs that wrap each character
gsap.set(_elName, { perspective: 400 });
tl.from(chars, {
duration: 0.8,
opacity: 0,
scale: 0,
y: 80,
rotationX: 180,
transformOrigin: "0% 50% -50",
ease: "back",
stagger: 0.01
});
}
A few things to watch though. As i use H1 for texts... that is deliberately. You do need to format your HTML text somewhat, if you donot, you probably will not see a SplitText animation. Ofcourse you can format it any way you want, but it has to have some formatting before running SplitText on it.
Hope this helps.
- larryvanwave-ffCommunity Member
This is great! thank you for going through the steps and showing the code breakdown for this. I am not sure how you figure all this out, but you are amazing. I am going to add this code in my file, and will test it out.