framer / motion

Open source, production-ready animation and gesture library for React
https://framer.com/motion
MIT License
23.44k stars 786 forks source link

[BUG] Offset Distance on SVG elements are placed in the wrong place. #1450

Open ShaeS opened 2 years ago

ShaeS commented 2 years ago

Describe the bug https://codesandbox.io/s/framer-motion-motion-along-a-path-41i3v

I wanted to do something similar to the code in this sandbox, but rather than running a div along the path I wanted to run an svg rect along the path. When adding offsetDistance to an svg element it renders offset-distance as a property on the rect, rather than adding it to the style tags, which is not valid and does not work.

Even if you add offsetDistance as a property of the style object, it removes it from the style tags and adds it to the rect. However, this only seems to happen with a MotionValue. if you hardcode an offsetDistance on the style tags it works properly.

Steps to reproduce https://codesandbox.io/s/framer-motion-motion-along-a-path-forked-r6u87

Steps to reproduce the behavior:

  1. Go into the forked sandbox and see the three circles I have added.
  2. The red circle uses the same method of animation as the div in the original sandbox, but upon inspecting the HTML you will see the offset-distance is applied to the root of the circle which is invalid.
  3. The orange circle is an alternative method of animating using useMotionValue and applying the value directly to the style tags, but upon inspecting the HTML you will see the offset-distance is applied to the root of the circle which is invalid.
  4. The green circle is not animated, but has a hardcoded '50%' on the style tags offsetDistance this applies the offset-distance to the style tags properly and shows the circle to be moved 50% along the path.

Expected behavior

Animating offsetDistance on an svg element should apply the property to the style tags so it animates properly in the same way it does for a div.

sebastiangraz commented 2 years ago

I was able to reproduce the same issues you are running into. As a workaround for now you might be able to animate css variables as described here https://www.framer.com/docs/component/###animating-css-variables

example:

<motion.g
initial={{ "--offset": "0%" }}
animate={{ "--offset": "100%" }}
transition={{
  duration: 1,
}}
style={{
  offsetDistance: "var(--offset)",
  offsetRotate: "0deg",
  offsetPath: `path("M12.68 9.85c.56-2.5.72-7.27-2.81-8.31C5.04.1-.94 1.44 1.61 6.72c2.55 5.27 7.2 6.35 12.39-.63")`
}}
>
...
commanderking commented 2 years ago

Thanks for bringing this issue up, and sharing a workaround! Seeing the example here was a real time saver when I ran into a similar issue.

marvimarvv commented 1 year ago

Duuuude I wish I found this earlier! 😿😆 But yes, can confirm that the bug is still there!

wilsonhou commented 1 year ago

can confirm this bug's still here :( this one sucked up a day. thanks for the workaround!!

TevinZielke commented 11 months ago

For anyone trying to use a calculated motionValue, you can use this syntax:


style={{
 offsetPath: "path(yourPath)",
 ['--offsetDistance' as string]:  yourMotionValue,
 offsetDistance: 'var(--offsetDistance)',
}}