DEV Community

Lucky Hamster
Lucky Hamster

Posted on

I need help in fixing a animation bug

The below JavaScript code fetches the path from a svg image. The svg image is particularly complex, and looks like this.

function initializeAnimation() {
    fetch('assets/img.svg')
        .then(response => response.text())
        .then(svgContent => {
            const parser = new DOMParser();
            const svgDoc = parser.parseFromString(svgContent, 'image/svg+xml');
            const originalPath = svgDoc.querySelector('path');

            if (!originalPath) return;

            const animationSvg = document.querySelector('.border-line');
            const viewBox = svgDoc.querySelector('svg').getAttribute('viewBox');

            if (viewBox) {
                animationSvg.setAttribute('viewBox', viewBox);
            }

            const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.setAttribute('d', originalPath.getAttribute('d'));
            animationSvg.appendChild(path);

            const pathLength = path.getTotalLength();
            let trailLength = pathLength * 0.01;
            let isComplete = false;

            function resetAnimation() {
                trailLength = pathLength * 0.01;
                path.style.strokeDasharray = `${trailLength} ${pathLength - trailLength}`;
                path.style.strokeDashoffset = 0;
                path.style.stroke = 'var(--on-surface)';
                path.style.strokeWidth = '5';
                isComplete = false;
                startTime = performance.now();
            }

            let startTime = performance.now();

            function animate(currentTime) {
                const elapsed = currentTime - startTime;

                if (!isComplete) {
                    trailLength = Math.min(pathLength * (0.01 + elapsed/50000), pathLength);
                    path.style.strokeDasharray = `${trailLength} ${pathLength - trailLength}`;

                    if (trailLength >= pathLength) {
                        isComplete = true;
                        path.style.stroke = 'var(--on-primary-container)';
                        path.style.strokeWidth = '8';
                        setTimeout(resetAnimation, 20000);
                    }
                }

                const currentOffset = parseFloat(path.style.strokeDashoffset || 0);
                const newOffset = currentOffset - 1;

                if (Math.abs(newOffset) >= pathLength) {
                    path.style.strokeDashoffset = 0;
                } else {
                    path.style.strokeDashoffset = newOffset;
                }

                requestAnimationFrame(animate);
            }

            requestAnimationFrame(animate);
        })
        .catch(error => console.error('Error loading SVG:', error));
 } 
Enter fullscreen mode Exit fullscreen mode

So the issue is that a perfect infinitely looping animation is not created. It just stops midway. And after that resumes its journey. I have tried debugging it, and it appears that some frames are not visible. With that said, I'm unaware of the root cause of the problem.

Screenshot of what actually happens.

For reference I have attached my CSS and HTML code.

<div class="profile-container">
    <div class="image-wrapper">
        <img src="assets/profile.jpg" alt="Eagle picture" class="profile-photo">
        <svg class="border-line" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
            <use href="#path"/>
        </svg>
    </div>
Enter fullscreen mode Exit fullscreen mode
  .profile-container {
    display: flex;
    align-items: center;
    gap: 2rem;
    margin-bottom: 2rem;
}

.image-wrapper {
    position: relative;
    width: 250px;
    height: 250px;
}

.profile-photo {
    width: 250px;
    height: 250px;
    position: relative;
    object-fit: cover;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    mask-image: url(assets/img.svg);
}

.border-line {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.border-line path {
    fill: none;
    stroke: var(--on-surface);
    stroke-width: 5;
    vector-effect: non-scaling-stroke;
}

@media (max-width: 768px) {
    .profile-container {
        flex-direction: column;
        text-align: center;
    }

    .image-wrapper {
        width: 350px;
        height: 350px;
    }

    .profile-photo {
        width: 350px;
        height: 350px;
    }
}
Enter fullscreen mode Exit fullscreen mode

Here is the link to the SVG File.

Top comments (0)