Controlling a timeline of all instances of a symbol elegantly


(Steve) #1

I am unable to elegantly query all instances of symbol, then perform an action on a timeline.

I’m currently giving each instance a unique ID, then list those in the script. It works but its clunkiness drives me nuts.

I KNOW I can use “getSymbolInstancesByName("")” to fetch efficiently but I’m doing something wrong here:

	//*********** Option A) This works but is convoluted because those are all symbol instances, not unique symbols
	//defining symbol and timeline to target requires me to give each instance a unique ID. Silly!!!
	//currSymbolInstance =  hypeDocument.getSymbolInstanceById('ball1');
	//currTimeLineName = 'Main Timeline';
	//currSymbolInstance2 = hypeDocument.getSymbolInstanceById('ball2');
	//currTimeLineName = 'Main Timeline';
	//currSymbolInstance3 = hypeDocument.getSymbolInstanceById('ball3');
	//currTimeLineName = 'Main Timeline';
	//currSymbolInstance4 = hypeDocument.getSymbolInstanceById('ball4');
	//currTimeLineName = 'Main Timeline';
	//************* Option B) This doesn't work for some reason. Fetching by instanceName: 

	//currSymbolInstance.currTimeLineName = 'Main Timeline';

	//************ Option C) Again trying to fetch by instanceName but no cigar ************
//	var allSymbolInstances = hypeDocument.getSymbolInstancesByName('ball1');
// 	for (var i = 0; i < allSymbolInstances.length; i++) {
// 		var symbolInstance = allSymbolInstances[i];
// 		currTimeLineName = 'Main Timeline';
//	 }

// doing some calculation here. Deleted for brevity.

// This works with Option A) but is totally redundand:
//Would love to just do this once by instanceName
		var duration = currSymbolInstance.durationForTimelineNamed('Main Timeline');
		var time = (percentPosition * duration);
		currSymbolInstance.goToTimeInTimelineNamed(time, 'Main Timeline');
		var duration = currSymbolInstance2.durationForTimelineNamed('Main Timeline');
		var time = (percentPosition * duration);
		currSymbolInstance2.goToTimeInTimelineNamed(time, 'Main Timeline');
		var duration = currSymbolInstance3.durationForTimelineNamed('Main Timeline');
		var time = (percentPosition * duration);
		currSymbolInstance3.goToTimeInTimelineNamed(time, 'Main Timeline');
		var duration = currSymbolInstance4.durationForTimelineNamed('Main Timeline');
		var time = (percentPosition * duration);
		currSymbolInstance4.goToTimeInTimelineNamed(time, 'Main Timeline');

I’m listing some links to posts related to my problem below for completeness sake.

Or should I query by class?


(Loves Hype) #2

Here is a example for getting them by name (20,0 KB)

// get all the symbols based on name with Hype API
var ballSymbolInstances = hypeDocument.getSymbolInstancesByName('ball');
// loop over them using i as a counter variable
for (var i=0; i<ballSymbolInstances.length; i++) {
	// create a shortcut in a variable extracting the current index i from the array ballSymbolInstances
	var symbolInstance = ballSymbolInstances[i];
	// tell the symbol instance to play
	symbolInstance.startTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);

Here is a example using class (26,7 KB)

// get the current scene element as each scene has it's own DOM tree branch
var currentSceneElement = document.querySelector('#'+hypeDocument.documentId()+' > .HYPE_scene[style*="block"]');
// get all ballSymbolElements by classname below the currentSceneElement (so no search in other scenes)
var ballSymbolElements = currentSceneElement.getElementsByClassName('ball');
for (var i=0; i<ballSymbolElements.length; i++) {
	// create a shortcut var in symbolInstance resolving the element to the Hype instance by id
	var symbolInstance = hypeDocument.getSymbolInstanceById(ballSymbolElements[i].id);
	// Test if that was successful as we can also theoretically assign a class 'ball' to an non symbol 
	if (symbolInstance) {
	 	// play that symbol instance
		symbolInstance.startTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);

Either works. By name doesn’t allow you to exclude some … with class you can create sub groups.

(Loves Hype) #3

I updated the class example to search only in the current scene.

(Steve) #4

Thank you, @MaxZieb. These are excellent examples.
I am playing with them (struggling with the rest of the script) but wanted to quickly let you know how much I appreciate your help!

(Loves Hype) #5

I added comments to the code … not in the download but here in the post above.

The main thing you have to understand (and I guess you struggle with) is the difference between a Instance and an Element. The web browser knows about HTML and parses it into an Element tree (DOM tree). Elements can be nested. In regular HTML files you would define them with HTML markup. In case of Hype the Runtime renders the DOM Element tree dynamically/on-the-fly through Javascript to your browser. So far so good. As Hype offers it’s own function and ideas like timelines etc. it has to keep references on the elements it creates and it manages it’s own internal state. You can influence that state with the HypeDocument API and the SymbolInstance API. Changes are then rendered back to the browser. In case of the two approaches on uses only the HypeDocument and SymbolInstance API (byName). Meaning we ask Hype about known symbolInstances and the act upon them through methods only known to Hype. The result appears in the browser. The second approach queries the actual DOM with browser functions (getElementsByClassName etc.) and therefor we must make sure we only search in the current scene and that we resolve the found elements through there ID back to their Hype representations (SymbolInstances). Hype offers the function hypeDocument.getSymbolInstanceById to do just that. After resolving the elements to instances we act upon them again through methods know to Hype and influence the Hype state like in first last example. The result appears again in the browser.

Hope this helps and is not too technical.

(Steve) #6

Thanks, @MaxZieb. It’s either the rest of my script or/and the very facts you elaborated above, but I’m stuck. My document can only control ONE symbol instance.

I’ve altered your “by name” sample file to include the rest of my script so you can see what’s happening: Some quite unexpected results on device orientation change…

getSymbolInstancesByNameDeviceOrientation_(h3) (25.3 KB) (hypev3)

(Jonathan Deutsch) #7

The problem with the code is that the window.ondeviceorientation handler you set up is only calling goToTimeInTimelineNamed on a single symbolInstance. This symbolInstance happens to be the last one that you are looping with in the above code.

Instead, you’ll want to again loop through all symbol instances if you want to set all the symbol instances (sorry that this sounds redundant!).

So your code would look like:

window.ondeviceorientation = function(event) {

    // ....

		var position = 1500 + (delta * 160);
		position = Math.floor(position);

		var ballSymbolInstances = hypeDocument.getSymbolInstancesByName('ball');
		for (var i=0; i<ballSymbolInstances.length; i++) {
			var symbolInstance = ballSymbolInstances[i];
			var percentPosition = (position / 30000); 
			var duration = symbolInstance.durationForTimelineNamed('Main Timeline');
			var time = (percentPosition * duration);
			symbolInstance.goToTimeInTimelineNamed(time, 'Main Timeline');

    // ....

(Steve) #8

Thank you, @Jonathan. Makes absolute sense. In retrospect…
Your help is highly appreciated.