javascripttypescriptdenofreshjs

JavaScript Animation Not Firing in Deno Fresh Island


I am practicing Deno Fresh, and currently I am attempting to learn how to add animations to islands. I have written the basic island below, including an animation method.

export default function StartAnimation() {
    function animation(): void {
        const _id = setInterval(frame, 10);
        const target = document.getElementById("target");
        let degree = 1;

        function frame() {
            target!.style.transform = `rotate(${degree}deg)`;
            if (degree === 360) {
                degree = 0;
            } else {
                degree++;
            }
        }
    }

    return (
        <div id="frame">
            <div id="target" onLoad={animation}>Test animation</div>
        </div>
    )
}

When running deno task start, I get no errors, and the div appears without issue, but the animation does not run.

Is there anything wrong with my code, and more generally is there a standard way to add animations to islands within Deno Fresh?


Solution

  • A good place to start understanding the fundamentals of preact (which fresh uses), would be the preact tutorial.

    To answer your question specifically though, what you're looking for is the useEffect hook. Essentially, useEffect runs once on an element render (if you pass zero dependencies like I did here) which is exactly what you wanted out of the onLoad.

    Something like this should work:

    import { useEffect } from "preact/hooks";
    
    export default function StartAnimation() {
        useEffect(() => {
            const _id = setInterval(frame, 10);
            const target = document.getElementById("target");
            let degree = 1;
    
            function frame() {
                target!.style.transform = `rotate(${degree}deg)`;
                if (degree === 360) {
                    degree = 0;
                } else {
                    degree++;
                }
            }
        }, []);
    
        return (
            <div id="frame">
                <div id="target">Test animation</div>
            </div>
        )
    }