DEV Community

Cover image for Path Motion Methods
Suni
Suni

Posted on

Path Motion Methods

I collect several implementations of Path Motion and summarizing my own evaluations of them.

You can click on my blog to check the specific effect.

1. CSS

First, the first method is the CSS way.

Using offset-path, and employing animation to make offset-distance go from 0% to 100%.

offset-path: path('M179.43,103.86 ...');
animation: move 3000ms infinite ease-in-out;
Enter fullscreen mode Exit fullscreen mode

2. SVG

The second, SVG

<path
    fill='none'
    stroke='lightgrey'
    d='M179.43,103.86 ...'
/>

<rect width="16" height="16" fill='rgb(75, 85, 99)'>
    <animateMotion
        dur='3s'
        rotate='auto'
        repeatCount='indefinite'
        path='M179.43,103.86 ...'
        calcMode='spline'
        keyTimes='0; 1'
        keySplines='0.5 0 0.5 1'
    />
</rect>
Enter fullscreen mode Exit fullscreen mode

3. JS

The last is control through JavaScript code.

import { animate } from 'motion'
import { useEffect, useRef } from 'react'
import { getPointAtLength, getTotalLength } from 'svg-path-commander'

const d = 'M179.43,103.86 ... '
const pathLength = getTotalLength(d)

export default function JSMotion() {
    const ref = useRef<HTMLDivElement>(null)

    useEffect(() => {
        if (ref.current) {
            animate(0, 100, {
                repeat: Infinity,
                ease: 'easeInOut',
                onUpdate: latest => {
                    const currentLength = (latest / 100) * pathLength
                    const { x: currentX, y: currentY } = getPointAtLength(d, currentLength)
                    ref.current!.style.left = currentX + 'px'
                    ref.current!.style.top = currentY + 'px'

                    const { x: nextX, y: nextY } = getPointAtLength(d, currentLength + 1)
                    const dx = nextX - currentX
                    const dy = nextY - currentY
                    const angle = Math.atan2(dy, dx) * (180 / Math.PI) + 90

                    ref.current!.style.rotate = angle + 'deg'
                },
                duration: 3
            })
        }
    }, [ref.current])

    return (
        <div className=' relative w-full h-[400px] bg-gray-50 rounded border'>
            <div ref={ref} className='w-4 h-4 bg-gray-600 absolute'></div>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Experience

CSS is relatively simple and can be directly applied in a normal HTML environment. The SVG approach, however, relies on a stable SVG environment, where the size is scaled according to the SVG dimensions. Fine-tuning the easing effect requires using keySplines, which demands some careful adjustment.

The movement in CSS is similar to a relative offset effect. In contrast, SVG involves setting x and y values within the SVG environment.

For JavaScript, the implementation depends on an animate library, a path utility library (svg-path-commander), and some calculations.

For simple loop animations or single-play animations, CSS is more convenient and efficient. SVG can quickly scale according to the page size.

JavaScript, on the other hand, can orchestrate multiple playback logics and is suitable for complex animations.

Top comments (0)