Checking if a scene transition is in progress

Hey everyone,

I just had this cool idea for figuring out if a scene is transitioning between two scenes in Tumult Hype. Basically, the idea is to check if two scenes are visible at the same time.

Here's how we can do it:

  1. Find the document root element: Use the Hype API to get the document ID.
  2. Search for visible scenes: Query the document to see which Hype scenes are currently visible.

If more than one scene is set to display: block, then we know a transition is happening. Here's a quick snippet to illustrate:

var rootElement = document.getElementById(hypeDocument.documentId());
var visibleScenes = rootElement.querySelectorAll('.HYPE_scene[style*="display: block"]');

if (visibleScenes.length > 1) {
    // Execute your code here
    console.log("Transition happening!");
} else {
    console.log("No transition.");
}
1 Like

I guess it would depend on why you want to know. But I suppose you could also check the on Unload and on load of a scene ?.

function sceneWillChange(hypeDocument, element, event) {
			hypeDocument.customData.loaded = 1
 		console.log(hypeDocument.currentSceneName(), 'scene Will Change')
 		 hypeDocument.customData.sceneTrans = 1
			 
	}
	
	function sceneDidChange(hypeDocument, element, event) {
		 
			
 			 if (hypeDocument.customData.loaded > 0 ) {
 			hypeDocument.customData.sceneTrans = 0
 			console.log('scene Did Change to',hypeDocument.currentSceneName())
 			}
 			 
 			
 		
	}
	
 
	if("HYPE_eventListeners" in window === false) {
	
		window.HYPE_eventListeners = Array();
	}
 
	window.HYPE_eventListeners.push({"type":"HypeSceneLoad", "callback":sceneDidChange});
	
	window.HYPE_eventListeners.push({"type":"HypeSceneUnload", "callback":sceneWillChange});
	 
	 </script>

Is the target to do something in between time ?

1 Like

The load/unload method wouldn't work on the newer 'Page Turn' transition, at least.

1 Like

Just thinking about that.. I assume because the events happen at roughly the. same time and therefore register at the end.

So @MaxZieb 's idea for looking for both scene would work better if you had an easy way to monitor it
(listen for a scene state change )

Half me half ChatGPT.
Not sure how practical it is..?

Placed in the head

<script> 
function hypeLoadCallback(hypeDocument, element, event) {
    let firstLoad = true;

    const rootElement = document.getElementById(hypeDocument.documentId());
    const scenes = rootElement.querySelectorAll('.HYPE_scene');

    console.log(scenes);

    // Debounce function
    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    // MutationObserver configuration
    const config = { attributes: true, attributeFilter: ['style'] };

    // Debounced function
    const debouncedFunction = debounce(function(displayValue) {
        console.log(hypeDocument.currentSceneName());
        console.log('Display property is now:', displayValue);
        // Your custom function logic here
    }, 1500); // Adjust the delay as needed (1500ms in this case)

    // MutationObserver callback
    const callback = function(mutationsList, observer) {
        if (firstLoad) {
            firstLoad = false;
            return;
        }

        for (let mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
                const displayValue = window.getComputedStyle(mutation.target).display;
                console.log('Display property:', displayValue);
                debouncedFunction(displayValue);
            }
        }
    };

    // Create and start the observer for all scenes
    scenes.forEach(scene => {
        const observer = new MutationObserver(callback);
        observer.observe(scene, config);
    });
}

if (typeof HYPE_eventListeners === "undefined") {
    window.HYPE_eventListeners = Array();
}

window.HYPE_eventListeners.push({"type":"HypeDocumentLoad", "callback":hypeLoadCallback});

  </script>

Hey Mark,

Your approach is observer-driven, actively monitoring state changes. In my method, I used it during a transition to passively call it when necessary, especially if I am still in a transition state.

ChatGPT performs well with sufficient context and documentation. Lately, I've been enjoying Claude too, and I'm currently paying for both.

The code you posted still needs some callback logic and or way to register listeners. Also, you probably don't need a first load check as HypeDocumentLoad gets called only once per document. Therefore, if you keep the observer locked to your document root, there is no redundancy. Observers only fire on state changes, so a debouncer is likely unnecessary as well.

1 Like

Ah thanks Max for the context.
Starting to like ChatGPT a bit more. Although you still have to keep an eye out for its logic bombs.
And make sure you understand what is is doing. I find I am mainly using it to write out things I am a bit lazy to dig round in my memory or look up again on how to do. Like the Observer structure.
I also always try and post back to it my code, so it can learn from it and what I changed that works better than what it gave me.

1 Like

Exactly, But the observer is firing straight away on HypeDocumentLoad.
I think because the styles are still updating in the browser. I did a test with a delay

setTimeout(() => {
          scenes.forEach(scene => {
        const observer = new MutationObserver(callback);
        observer.observe(scene, config);
    });
        console.log('Observers started after delay');
    }, 1000); // Adjust delay as needed
 
}

Which seems to confirm this. As when used I do not get the firing at load time.

Please explain.

Your right about the debuncer, I put it in then never bothered to take it out.

1 Like

Here is an observer's perspective:
HypeTransitionObserver.hype.zip (25,4 KB)

What I mean is that you can use an observer with a specific root. Upon closer inspection, I noticed that you are already implementing this at a Hype scene level. In the example above, I applied it at a document level... I believe I should adopt your method, as the subtree flag and the style attribute tend to trigger it on any change. Although I am currently mitigating this by verifying the class name... it might be more efficient to follow your approach and observe only the necessary nodes. When time permits, I will revisit this.

2 Likes

Thanks,

That's exactly what I was finding when I started writing it out.

1 Like