Overview

Control a Timeline by scroll

Use the mouse wheel or touch delta to update a timeline's time.

import { Behaviour, PlayableDirector, serializeable } from "@needle-tools/engine";
import { Mathf } from "@needle-tools/engine";

// Example of setting a timeline's time 
// without relying on any HTML elements.
// Here we directly use the mousewheel scroll and the touch delta

export class ScrollTimeline_2 extends Behaviour {

    @serializeable(PlayableDirector)
    timeline?: PlayableDirector;

    @serializeable()
    scrollSpeed: number = 0.5;

    @serializeable()
    lerpSpeed: number = 2.5;

    private targetTime: number = 0;

    start() {

        this.timeline?.pause();

        // Grab the mousewheel event
        window.addEventListener("wheel", (evt: WheelEvent) => this.updateTime(evt.deltaY));

        // Touch events are a bit more complicated
        // We need to keep track of the last touch position
        // and calculate the delta between the current and the last position
        let lastTouchPosition = -1;
        window.addEventListener("touchmove", (evt: TouchEvent) => {
            const delta = evt.touches[0].clientY - lastTouchPosition;
            // We only want to apply the delta if it's not TOO big
            // e.g. when the user is scrolling the page
            if (delta < 10) this.updateTime(-delta);
            // Update the last touch position
            lastTouchPosition = evt.touches[0].clientY;
        });
    }

    private updateTime(delta) {
        if (!this.timeline) return;
        this.targetTime += delta * 0.01 * this.scrollSpeed;
        this.targetTime = Mathf.clamp(this.targetTime, 0, this.timeline.duration);
    }

    onBeforeRender(): void {
        if (!this.timeline) return;
        this.timeline.pause();
        this.timeline.time = Mathf.lerp(this.timeline.time, this.targetTime, this.lerpSpeed * this.context.time.deltaTime);
        this.timeline.evaluate();
    }
}