Imade defille

PHOTO EMBED

Sat Jan 11 2025 18:01:13 GMT+0000 (Coordinated Universal Time)

Saved by @Eden

<div class="pedal-path-container">    
    <div class="pedal-path">
        <img src="https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png">
        <img src="https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png">
        <img src="https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png">
        <img src="https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png">
        <img src="https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png">
    </div>
    <div class="road-overlay"></div>
</div>

<style>
    .pedal-path-container {
        width: 100%;
        height: 35px;
        overflow: hidden;
        position: relative;
    }
    
    .pedal-path {
        height: 100%;
        position: absolute;
        white-space: nowrap;
        will-change: transform;
    }
    
    .pedal-path img {
        height: 100%;
        width: auto;
    }
    
    .road-overlay {
        position: absolute;
        inset: 0;
        background: linear-gradient(
            to right,
            #140D3F 0%,
            transparent 10%,
            transparent 90%,
            #140D3F 100%
        );
        pointer-events: none;
    }
</style>

<script>
    class PedalPathAnimation {
        constructor() {
            this.container = document.querySelector('.pedal-path-container');
            this.path = document.querySelector('.pedal-path');
            this.imgSrc = 'https://d1yei2z3i6k35z.cloudfront.net/1970629/677599f123309_dsfgvdsv.png';
            this.wheelWidth = 0;
            this.animationId = null;
            this.position = 0;
            this.lastTime = null;
            this.speed = 0.3;

            // Bind methods
            this.init = this.init.bind(this);
            this.startRide = this.startRide.bind(this);
            this.stopRide = this.stopRide.bind(this);
            this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
            this.handleResize = this.handleResize.bind(this);

            // Initialize
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', this.init);
            } else {
                this.init();
            }
        }

        async init() {
            try {
                await this.setupPedalPath();
                this.addEventListeners();
            } catch (error) {
                console.error('Initialization error:', error);
            }
        }

        async loadWheelImage() {
            return new Promise((resolve, reject) => {
                const wheel = new Image();
                wheel.onload = () => resolve(wheel);
                wheel.onerror = (error) => reject(error);
                wheel.src = this.imgSrc;
            });
        }

        async setupPedalPath() {
            try {
                const wheel = await this.loadWheelImage();
                this.wheelWidth = wheel.width * (this.container.offsetHeight / wheel.height);
                const roadWidth = this.container.offsetWidth;
                const wheelCount = Math.ceil(roadWidth / this.wheelWidth) + 1;

                // Clear existing content
                this.path.innerHTML = '';
                
                // Add new images
                const fragment = document.createDocumentFragment();
                for (let i = 0; i < wheelCount; i++) {
                    fragment.appendChild(wheel.cloneNode());
                }
                this.path.appendChild(fragment);

                this.startRide();
            } catch (error) {
                console.error('Setup error:', error);
            }
        }

        startRide() {
            const animate = (timestamp) => {
                if (this.lastTime === null) {
                    this.lastTime = timestamp;
                }
                
                const elapsed = timestamp - this.lastTime;
                this.lastTime = timestamp;
                
                this.position = (this.position - (this.speed * elapsed)) % this.wheelWidth;
                this.path.style.transform = `translateX(${this.position}px)`;
                this.animationId = requestAnimationFrame(animate);
            };

            this.animationId = requestAnimationFrame(animate);
        }

        stopRide() {
            if (this.animationId) {
                cancelAnimationFrame(this.animationId);
                this.animationId = null;
                this.lastTime = null;
            }
        }

        handleVisibilityChange() {
            if (document.hidden) {
                this.stopRide();
            } else {
                this.startRide();
            }
        }

        handleResize() {
            this.stopRide();
            this.setupPedalPath();
        }

        addEventListeners() {
            document.addEventListener('visibilitychange', this.handleVisibilityChange);
            
            const resizeObserver = new ResizeObserver(this.handleResize);
            resizeObserver.observe(this.container);
        }

        cleanup() {
            this.stopRide();
            document.removeEventListener('visibilitychange', this.handleVisibilityChange);
            // ResizeObserver will be automatically disconnected when the element is removed
        }
    }

    // Initialize the animation
    const pedalAnimation = new PedalPathAnimation();
</script>
content_copyCOPY