Use the /collab command on Discord to gain access to the OneJS private repo. The repo offers early access to the latest features and fixes that may not yet be available on the Asset Store. An early preview of OneJS V2 is available on branch onejs-v2. It brings major performance improvements, zero-allocation interop, and a new esbuild workflow.
Menu

FadeTween

About

FadeTween is a simple component that wraps three Tweens: FadeIn, WaitTime and FadeOut. Those Tweens are called in order and repeated forever, so you can create an effect like this:

fadeTween example

Code used in the example

The code to create this example (AnnouncementText), is:

const texts = [
    "This is a test",
    "This is another test",
    "This is a third test",
    "This is a fourth test",
    "This is a fifth test",
];
export const AnnouncementText = () => {

    const [currentText, setCurrentText] = useState(texts[0]);

    const changeText = () => {
        const nextText = texts[Math.floor(Math.random() * texts.length)];
        setCurrentText(nextText);
    };

    return (
        <FadeTween waitTime={1000} fadeDuration={300} onFadeIn={null} onFadeOut={changeText}> 
            <label text={currentText}></label>
        </FadeTween>
    )
}

Steps to implement FadeTween:

1- Create a file called fade-tween.tsx

2- Copy this code:

import { Dom } from "OneJS/Dom";
import { h } from "preact";
import { useEffect } from "preact/hooks";
import { useRef } from "preact/hooks";
import { Tween, update } from "tweenjs/tween";

let tweenedOpacity = { value: 0 };

let fadeInTween: Tween<{ value: number }>;
let waitTween: Tween<{ value: number }>;
let fadeOutTween: Tween<{ value: number }>;
let currentFadeDuration = 0;
let currentWaitTime = 0;
export const FadeTween = (props: { children?: any, onFadeIn?: Function, onFadeOut?: Function, fadeDuration?: number, waitTime?: number }) => {

    const divRef = useRef<Dom>();


    const stopAllTweens = () => {
        if (fadeInTween) {
            fadeInTween.stopChainedTweens();
            fadeInTween.stop();
        }
        if (waitTween) {
            waitTween.stopChainedTweens();
            waitTween.stop();
        }
        if (fadeOutTween) {
            fadeOutTween.stopChainedTweens();
            fadeOutTween.stop();
        }

        fadeInTween = undefined;
        waitTween = undefined;
        fadeOutTween = undefined;
    }

    useEffect(() => {
        return () => {
            stopAllTweens();
        }
    }, []);

    // Fade is already running
    if (typeof fadeInTween !== "undefined") {

        // Fade duration or wait time changed. Need to restart the fade
        if (currentFadeDuration !== props.fadeDuration || currentWaitTime !== props.waitTime) {
            stopAllTweens();
        }
    }




    if (typeof fadeInTween === "undefined") {
        currentFadeDuration = props.fadeDuration;
        currentWaitTime = props.waitTime;

        // Fade in tween (Will call onFadeIn when complete & updates opacity style onUpdate)
        fadeInTween = new Tween(tweenedOpacity).to({ value: 1 }, props.fadeDuration ? props.fadeDuration : 700)
            .onUpdate(() => {
                divRef.current.style.opacity = tweenedOpacity.value.toString();
            })
            .onComplete(() => {
                if (props.onFadeIn) {
                    props.onFadeIn();
                }
            });

        // Wait tween (Just a delay)
        waitTween = new Tween(tweenedOpacity).delay(props.waitTime ? props.waitTime : 0);

        // Fade out tween (Will call onFadeOut when complete & updates opacity style onUpdate)
        fadeOutTween = new Tween(tweenedOpacity).to({ value: 0 }, props.fadeDuration ? props.fadeDuration : 700)
            .onUpdate(() => {
                divRef.current.style.opacity = tweenedOpacity.value.toString();
            })
            .onComplete(() => {
                if (props.onFadeOut) {
                    props.onFadeOut();
                }
            });


        if (currentWaitTime > 0) {
            fadeInTween.chain(waitTween.chain(fadeOutTween.chain(fadeInTween))).start();
        } else {
            fadeInTween.chain(fadeOutTween.chain(fadeInTween)).start();
        }
    }

    return (
        <div ref={divRef}>
            {props.children as any}
        </div>
    )
}

function animate(time) {
    requestAnimationFrame(animate)
    update(time)
}
requestAnimationFrame(animate);

3- Use it like this:

<FadeTween>
    // any children here
</FadeTween>

Where:

  • waitTime: Time between fadeIn and fadeOut effect
  • fadeDuration: Time that takes to animate the fadeIn and fadeOut animation
  • onFadeIn: A function that will be called when the children are completly visible
  • onFadeOut: A function that will be called when the children are completly invisible

Ideas for the future:

  • Implement a prop to set the default state (start fadeIn or fadeOut)
  • Implement a prop to decide if the fadeIn and out should be infinite
  • ???