DEV Community

easyoon
easyoon

Posted on • Originally published at devblogeasyoon.xyz

[Translations] Implementing Animations with Throttle in JavaScript

Original Article Link


Implementing Animations with Throttle in JavaScript

This document explains how to improve animation performance using throttle in JavaScript and applies throttle to solve the issue of choppy scroll animations. It also compares the differences before and after applying throttle.

What is Throttle?

Throttle is a technique that limits a function to be called 'at most once' within a 'certain time interval'. In other words, even if an event occurs multiple times within a short period, the function will only be executed once within the time interval set by the throttle. For example, if a function has a throttle of 100ms, even if the event occurs 10 times in 1 second, the function will be executed a maximum of 10 times (at 100ms intervals).

Where is Throttle Used?

Throttle can be used in the following situations:

  • Preventing performance degradation due to excessive event triggering: When events such as scrolling, mouse movement, and window resizing occur frequently in a short period, the event handler can be executed excessively, causing performance issues. Throttle is used to mitigate this.
  • Making animations smoother: When it is necessary to express continuous changes, such as scroll animations, the animation may be choppy or stutter depending on the event frequency. Using throttle can make animations smoother.

Problem: Stuttering and Choppy Scroll Animations

An attempt was made to implement a smooth scroll animation according to the scroll wheel event, but before applying throttle, the animation was choppy.

Reason: This is because the wheel event occurs at a very high rate, causing the window.scrollBy function to be called excessively, preventing the browser from processing all requests.

Comparison

1. Code Before Applying Throttle

useEffect(() => {
    const container = scrollContainerRef.current;
    if (!container) return;

    const handleWheel = (event) => {
        event.preventDefault();

        window.scrollBy({
            left: event.deltaY,
            behavior: 'smooth'
        });
    };

    container.addEventListener('wheel', handleWheel);

    return () => {
        container.removeEventListener('wheel', handleWheel);
    };
}, []);
Enter fullscreen mode Exit fullscreen mode

In this code, the handleWheel function is executed every time a wheel event occurs. This function calculates the scroll amount using the deltaY value of the event and scrolls by calling the window.scrollByfunction. The problem is that the wheel event can occur multiple times in a very short period, which causes window.scrollBy to be called excessively, resulting in a choppy animation.

2. Code After Applying Throttle

useEffect(() => {
    const container = scrollContainerRef.current;
    if (!container) return;
    let throttleTimer;

    const handleWheel = (event) => {
        if (throttleTimer) return;

        event.preventDefault();

        throttleTimer = setTimeout(() => {
            window.scrollBy({
                left: event.deltaY,
                behavior: 'smooth'
            });
            throttleTimer = null;
        }, 16);
    };

    container.addEventListener('wheel', handleWheel);

    return () => {
        container.removeEventListener('wheel', handleWheel);
    };
}, []);
Enter fullscreen mode Exit fullscreen mode

In the throttled code, the throttleTimer variable is used to manage function execution. The process works as follows:

  • When the handleWheel function is called, it checks if throttleTimer exists.
  • If throttleTimer exists (meaning a previously set timer is still active), the function returns immediately. This prevents new scroll requests from being processed while a scroll animation is already in progress.
  • If throttleTimer does not exist, event.preventDefault() is called to prevent the default scroll behavior, and setTimeout is used to execute the window.scrollBy function after 16ms.
  • Inside the setTimeout callback function, throttleTimer is set to null, resetting the throttle and allowing the function to be called again after the delay.

3. Potential Improvements

  • Initial Delay of setTimeout

    setTimeout is used to implement the throttling mechanism. setTimeout executes the callback function after the specified delay (16ms in this case). Consequently, when the first wheel event occurs, window.scrollBy is invoked after a 16ms delay. This initial delay can lead to a perceived lack of immediate responsiveness, potentially being interpreted as stuttering, particularly with rapid wheel movements. (Further improvements will be explored in the future...)

Top comments (0)