Controlling Symbols with Javascript

Many of these things can be done without Javascript using Custom Behaviors and Symbol Element Actions, but I thought it would be nice to have some simple Javascript examples for controlling symbol timelines.

Playing a timeline on a specific Symbol

  1. Set the Unique Element ID on the Symbol element in the Identity inspector to ‘mySymbolInstance’

  2. Run the following javascript to play the Main Timeline on mySymbol:

     var symbolInstance = hypeDocument.getSymbolInstanceById('mySymbolInstance');
     symbolInstance.startTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);
    

Playing a timeline on all instances of a symbol

  1. Add multiple instances of your symbol to the scene

  2. Run the following javascript

     var allSymbolInstances = hypeDocument.getSymbolInstancesByName('Symbol');
     for (var i = 0; i < allSymbolInstances.length; i++) {
     	var symbolInstance = allSymbolInstances[i];
     	symbolInstance.startTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);
     }
    

Here is an example document: SymbolJavascriptDemo.zip (26.7 KB)

To get the parent symbol of a given element see this post: Getting the SymbolInstance for an element inside of a symbol.

18 Likes

This is the problem with coding/programming… one little thing is off and the whole thing stops working. I couldn’t figure out why I couldn’t get the timelines in the symbol working. I thought I named the Symbol with the Unique Element ID field, but all I did was name one of the elements INSIDE the Symbol.

Anyway, now that I can control Symbols, I was able to fix a pesky responsive issue. My massive project is nearing 3% complete. Yes… only 3%. Heh, so slow.

2 Likes

This really helped me! Thanks for the great documentation!

2 Likes

Hi, so I have a bit of a complex animation that contains multiple symbols. It is basically a gallery that flips through 10 screens. The screens are controlled by 10 buttons (that is also symbols). I’ve used this code above to run the gallery and it works fine, problem is I have to select the buttons in order from 1-10 for it to trigger the animation inside of the gallery symbol. This is a problem as the user should be able to select any of the 10 buttons (randomly) to trigger the timeline inside of the gallery symbol.

Here is my file that will probably make more sense: TheTrail_gallery.zip (665.8 KB)

Please advise, I think it might have something to do with the ‘kDirectionForward’ in the code, not sure.

I think the issue is in how your timelines are setup inside the textGallery symbol. For example the text006_in timeline moves the text005 element away and brings in the text006 element. However if you had shown the text004 element previously, there’s nothing that would move this out of the way. And due to the layer ordering, 004 will still appear above.

The two possible fixes for this would be:

  1. Use Relative Timelines. On a relative timeline, the first keyframe represents wherever the element is. So on each timeline you could effectively make animations that move all the other text00X elements out of the way, and they’ll only run that if they are out of place.

  2. Use JavaScript to keep track of which element is being shown. Then you can run specific code to have timelines move the right elements out of the way and show the other ones.

There’s a third solution using pause timeline actions and continue timeline creatively, but that is probably more complex than it is worth.

1 Like

Hi thanks, I tried that but that just messes up my keyframes inside all of the timelines inside of the gallery symbol. I have moved each element out of the way as suggested, but the buttons are outside of the symbol and not effected by any overlays. Shouldn’t the buttons control which timeline animation to trigger once selected?

At the moment I have to select the buttons in order 1-10 for the timelines to play. Each timeline run on it’s own, correct? or am I missing something here?

(*sorry, I am a bit new in this software. Been using Adobe Edge Animate for about 2 years, it’s a bit difficult to wrap my head around timeline triggers)

I believe the buttons are functioning correctly, but the logic behind your timelines will not achieve the desired effect.

Each timeline is run on its own, so let’s say you have this flow:

First Hit button 1

  • Text Element 9 goes out to the left (not seen because it is below other elements)
  • Text Element 1 comes in from the right

Then, Hit button 4

  • Text element 3 goes out to the left (not seen because it is below other elements)
  • Text Element 4 come in from the right (not seen because Text Element 1 is still there and layered above)

So hitting button 4 won’t do anything because there was never any animations that would remove text 1. Thus Text Element 1 is still shown.

In short, you need to trigger an animation that makes sure the other text elements are animated out to show the current text element.

1 Like

If I hide each element (not needing to be visible) on each timeline, will this solve my problem? Or will I need to add an animation to each element, moving it off the symbol layout? for example:
Text element 1 animates out to the left and then hides. Text element 2 comes in from right and is visible. Then, when button 7 is pressed, Text element 1-6 will hide to only have Text element 7 visible?

Hiding is a good technique that could be a part of it, but won’t wholly solve your problem - in the above example you do aren’t animating out text element 2, for example. You need a general way to animate out any slide that happens to be on.

The general non-code solution for doing this in Hype is with the before mentioned relative keyframes. I’ve attached an example that shows this. All elements except the first start as hidden. There’s one relative timeline, HideAll, that moves out all elements out to the left and then hides them. After that is kicked off, a non-relative timeline, RevealX, animates the correct item from right to center. Because this timeline is after the HideAll one, it doesn’t conflict even though it is animating one of the same elements.

RelativeShowing.hype.zip (17.6 KB)

I did not use overflow hidden no the group to better illustrate how this works; instead I just have some partially transparent boxes on the left/right.

1 Like

If I was going to do this in JS instead of the timelines.

I would put all the slides in a single group and offset to the right side of the scene except slide 1 which will be showing.

I would then just use the Javascript to move the group.

For the buttons we simply use the symbol name of the buttons to help us calculate the amount of left movement we need. (The symbol names all end in a index number )

In both functions we try and control some of the behaviour if people mash the buttons or arrows.

Buttons code ( all buttons point to this function)

	var slider = hypeDocument.getElementById('slider')
	     
	  
	hypeDocument.setElementProperty(slider, 'opacity', 0, 1, 'easeinout')//-- fade out	
	var thisSlide = Number(hypeDocument.getSymbolInstanceById(element.id).symbolName().slice(-2)); //-- get the last 2 characters of the button's symbol name as a number.
  
	var newLeft = 0 -   (657  * (thisSlide -1)) //-- 657 is the width of each lide. we Times that by the number from the button.
 

	 //-- slide
	 setTimeout(function(){ 
	 
	 if (hypeDocument.getElementById('slider').style.opacity == 0) { //-- try not to re slide two soon
	 
 hypeDocument.setElementProperty(slider, 'left', newLeft) //-- slide to new left.
 }
hypeDocument.setElementProperty(slider, 'opacity', 1, 1.0, 'easeinout')//-- fade back in

 
	}, 1010);  

For the arrows we just need to advance or decrease the left by a single amount each time.
But we also need to put limiters on the max/min left

Arrow code ( Both arrows point to this function)

var rightArrow = hypeDocument.getElementById('right')
var leftArrow = hypeDocument.getElementById('left')
var min_Left =657
var max_Left = -6570 
 

//-- disable arrows so we do not go to early and get wrong left.
rightArrow.style.pointerEvents = "none"   
leftArrow.style.pointerEvents = "none"


var slider = hypeDocument.getElementById('slider')//-- Group the slides are in
	  	
 
var currentLeft =  hypeDocument.getElementProperty(slider, 'left')


window.newLeft = Math.floor(currentLeft + min_Left ) //go left
 
if (element.id == "right"){  //go right

 window.newLeft = Math.floor(currentLeft - min_Left) 
}

   
 if (window.newLeft < min_Left && window.newLeft  > max_Left ) { //-- limit going to far left or to far right
hypeDocument.setElementProperty(slider, 'left', window.newLeft, 1, 'easeinout')


  } 
  

 

setTimeout(function(){ //-- reste arrows
	
	
 
rightArrow.style.pointerEvents = "auto"
 

leftArrow.style.pointerEvents = "auto"
	
	}, 1050);  

TheTrail_gallery_MHv1.hype.zip (682.5 KB)

2 Likes

This worked, Bravo! Thanks to you I have working toggle switch for playing and pausing my buttons :slight_smile:

1 Like