Repository navigation
Marquee along SVG scaling issue #59
Copy link
Copy link
Open
Description
When implementing a different SVG path than the provided example, an issue came up for me. The offsetPath on the motion.div does not scale the same as the <svg><path></svg> above it. The size of the travel the images takes depends on the string value for path.
Sorry if this isn't explained well. I can get the SVG to scale, but the mapped motion.div's remain the size outlined by the value i pass to d={path}. Moving the motion.div inside the SVG doesn't do anything, but making the motion.div a motion.g now allows the SVG to scale the offset-path value.
UPDATED RETURN for marquee:
return (
<div
ref={container}
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
onPointerCancel={handlePointerUp}
className={cn("relative", className)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
viewBox={viewBox}
preserveAspectRatio={preserveAspectRatio}
>
{/* Path for visualization */}
<path
id={id}
d={path}
className="w-full"
stroke={showPath ? "currentColor" : "none"}
fill="none"
ref={pathRef}
/>
{/* Animate each item along the path */}
{items.map(({ child, repeatIndex, itemIndex, key }) => {
const itemOffset = useTransform(baseOffset, (v) => {
const position = (itemIndex * 100) / items.length;
const wrappedValue = wrap(0, 100, v + position);
return easing
? easing(wrappedValue / 100) * 100
: wrappedValue;
});
const x = useMotionValue(0);
const y = useMotionValue(0);
const zIndex = useTransform(currentOffsetDistance, (value) =>
calculateZIndex(value)
);
useEffect(() => {
const pathEl = pathRef.current;
if (!pathEl) return;
const totalLength = pathEl.getTotalLength();
const unsubscribe = itemOffset.on(
"change",
(value: string) => {
const percent = parseFloat(value) / 100;
const point = pathEl.getPointAtLength(
percent * totalLength
);
x.set(point.x);
y.set(point.y);
}
);
return unsubscribe;
}, [itemOffset]);
const cssVariables = Object.fromEntries(
(cssVariableInterpolation || []).map(
({ property, from, to }) => [
property,
useTransform(
currentOffsetDistance,
[0, 100],
[from, to]
),
]
)
);
return (
<motion.g
key={key}
className={cn(
"along-element relative",
draggable && grabCursor && "cursor-grab"
)}
style={{
offsetDistance: itemOffset,
zIndex: enableRollingZIndex ? zIndex : undefined,
translateX: x,
translateY: y,
...cssVariables,
}}
aria-hidden={repeatIndex > 0}
onMouseEnter={() => (isHovered.current = true)}
onMouseLeave={() => (isHovered.current = false)}
>
{child}
</motion.g>
);
})}
</svg>
</div>
);
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
danielpetho commentedon Aug 13, 2025
hey Daniel!
Sorry this is my bad, since I completely left out the responsivity part.
I will update the component soon, but in the meantime, pls check out this article.
It's a step by step tutorial for this exact component I wrote for Codrops, so integrating the correct scaling should be hopefully easy. The relevant part is at the Responsiveness section, with 3 different techniques how to make it truly responsive.
If you're having problem implementing it, please make a Codesandbox and I'll try to help.
dancrump1 commentedon Aug 14, 2025
No worries on updating. Your article made it super easy, but I enjoyed trying to figure out the strategies you outlined myself first. I'll grab that npm lib you pointed out and give that a try. It'll probably be way cleaner than what I could craft in my code-freeze time :D
danielpetho commentedon Aug 29, 2025
nice, I'm glad it worked!
the trick is actually from jhey, so full credits to him:)
I'm going to keep this open until it's fixed though.
dancrump1 commentedon Aug 30, 2025
Here is the current implementation I am running. Current assumptions are the svg viewbox sizing. These should be updated with the correct sizing for each SVG. Definitely not perfect! I'm sure you have something stronger than this already, it came basically from your article. Mostly posting for anyone struggling with using images.
chrome_skfYzzY7r4.mp4
danielpetho commentedon Sep 13, 2025
No I have the same implementation haha, so if anyone reading this have something better feel free to throw it here or open a PR:)
dancrump1 commentedon Nov 14, 2025
I'm dropping this into a website and noticed the mobile performance was a bit touchy. Asked Cursor to optimize performance for mobile and here's the output. Verified on personal mobile device, recalculating the path on screen resize is significantly faster, though the fidelity of the path for the images to follow is reduced for mobile. Still important to pass in a height and width for each SVG used.
No guarantees this is an improvement. Please review before implementing! My testing showed marked improvements, but may have missed critical bugs / issues.