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;
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>
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>
)
}
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.