Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Enable Animation #77

Open
aapatre opened this issue Apr 18, 2022 · 5 comments
Open

Feature Request: Enable Animation #77

aapatre opened this issue Apr 18, 2022 · 5 comments

Comments

@aapatre
Copy link

aapatre commented Apr 18, 2022

Hi @sneas, hope you are doing well
Is it possible to add a feature to animate the divider? :)

As done in this slider: https://github.com/OnurErtugral/react-image-comparison-slider

Thanks & Regards,
Antariksh

@sneas
Copy link
Owner

sneas commented Apr 18, 2022

Hi Antariksh,

There is no such functionality per-se, but you can build one yourself based on what the component already has. The code example would be:

const slider = document.getElementById('slider');

let direction = 'right';

let move = () => {
    slider.value = slider.value + 0.15 * (direction === 'right' ? 1  : -1);
    if (slider.value >= 100) {
       direction = 'left';
    }

    if (slider.value <= 0) {
        direction = 'right';
    }
}

let animationId;

let animate = () => {
  move();
  animationId = requestAnimationFrame(animate);
}

animationId = requestAnimationFrame(animate);

@aapatre
Copy link
Author

aapatre commented Apr 19, 2022

Thanks a lot, @sneas
I will try this out :)

@Vantadaga
Copy link

Is it possible to make this work with this project?

@saas786
Copy link

saas786 commented Jun 4, 2024

I've implemented this code and think it could be helpful to others. Sharing it here in case someone finds it useful. Feedback welcome to improve my code.

function animateImageComparison() {
    const slider = document.getElementById('slider');

    if (!slider) {
        return;
    }

    const originalValue = slider.value;
    // Amount to move the handle.
    const shakeAmount = 5;
    const shakeDuration = 300;
    const resetDuration = 300;

    let animationFrameId = null;

    const animateValue = (startValue, endValue, duration, onComplete) => {
        const startTime = performance.now();

        const step = (currentTime) => {
            const elapsedTime = currentTime - startTime;
            const progress = Math.min(elapsedTime / duration, 1);
            slider.value = startValue + (endValue - startValue) * progress;

            if (progress < 1) {
                animationFrameId = requestAnimationFrame(step);
            }
            else {
                onComplete();
            }
        };

        animationFrameId = requestAnimationFrame(step);
    };

    const cancelAnimation = () => {
        if (animationFrameId) {
            cancelAnimationFrame(animationFrameId);
            animationFrameId = null;
        }
    };

    const shake = () => {
        const moveRight = () => {
            animateValue(originalValue, Math.min(originalValue + shakeAmount, 100), shakeDuration, moveLeft);
        };

        const moveLeft = () => {
            animateValue(Math.min(originalValue + shakeAmount, 100), Math.max(originalValue - shakeAmount, 0), shakeDuration, reset);
        };

        const reset = () => {
            animateValue(slider.value, originalValue, resetDuration, cancelAnimation);
        };

        moveRight();
    };

    const handleVisibilityChange = (entries, observer) => {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                shake();
                // Stop observing after the element is in view.
                observer.disconnect();
            }
        });
    };

    const observer = new IntersectionObserver(handleVisibilityChange, {
        // Adjust the threshold as needed.
        threshold: 0.1,
    });

    observer.observe(slider);

    // Cancel ongoing animation if the page is unloaded or slider is out of view.
    window.addEventListener('beforeunload', cancelAnimation);

    document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
            cancelAnimation();
        }
    });
}

window.addEventListener('load', animateImageComparison);

@sneas
Copy link
Owner

sneas commented Jun 18, 2024

This is amazing, @saas786 ! Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants