Closed Mellis84 closed 3 years ago
Same here. Hover works fine, but I get an error on open.
variants={{
closed: { d: "M8.9,8.4h14.1" },
open: { d: "M8.888,8.888,23.112,23.112" },
hover: { d: "M5.9,8.4h20.1" },
}}
variants={{
closed: { d: "M8.9,23.6h14.1" },
open: { d: "M8.888,23.112,23.112,8.888" },
hover: { d: "M5.9,23.6h20.1" },
}}
Same here. But i don't think it is really a bug. Can't find a thing about it in the documentation 😿
As far as I understand, it doesn't morph the SVG, it just manipulate its positions. So, maybe when one of the variants has different paths it doesn't know what to do.
In my case, I've changed every h
inside my SVG to l
and it's working now.
variants={{
closed: { d: " M8.942, 8.421 L 23.058, 8.42" },
open: { d: "M 8.888, 8.888, L 23.112 ,23.112" },
hover: { d: "M 5.942, 8.421 L 26.058, 8.421" },
}}
This is just one line of a hamburger menu, so it's quite easy to change it by hand. Don't know about more complex SVGs. Illustrator, figma, xd and sketch each exported it a little bit different.
Here are the svg path properties for reference:
M = moveto L = lineto H = horizontal lineto V = vertical lineto C = curveto S = smooth curveto Q = quadratic Bézier curve T = smooth quadratic Bézier curveto A = elliptical Arc Z = closepath
I'm experiencing this issue when changing the amount of points inside of a <motion.path>
.
Here's a CodeSandbox demonstrating the issue:
https://codesandbox.io/s/wizardly-feather-qqv3q?file=/src/App.js
Click on the SVG and you should see the error:
I created a custom hook to solve this by using flubber
, useMotionValue
and animate
. Check it out:
function useSVGMorph(
d: string,
config: Parameters<typeof animate>[2] = {}
): MotionValue<string> {
const value = useMotionValue<string>(d);
React.useEffect(() => {
const interpolator = interpolate(value.get(), d);
animate(0, 1, {
...config,
onUpdate: (progress) => value.set(interpolator(progress))
});
}, [config, d, value]);
return value;
}
You can just pass the desired d
as the first argument and other options (like duration) as the second parameter, here is an example:
import {
animate,
motion,
MotionValue,
useCycle,
useMotionValue
} from "framer-motion";
import * as React from "react";
import { interpolate } from "flubber";
const shapes = {
rectangle: "M0,25 L100,25 L100,75 L0,75Z",
triangle: "M0,100 L50,0 L100,100Z",
square: "M0,0 L100,0 L100,100 L0,100Z"
};
function useSVGMorph(
d: string,
config: Parameters<typeof animate>[2] = {}
): MotionValue<string> {
const value = useMotionValue<string>(d);
React.useEffect(() => {
const interpolator = interpolate(value.get(), d);
animate(0, 1, {
...config,
onUpdate: (progress) => value.set(interpolator(progress))
});
}, [config, d, value]);
return value;
}
export default function App() {
const [shape, cycleShape] = useCycle("rectangle", "triangle", "square");
const d = useSVGMorph(shapes[shape as keyof typeof shapes], {
duration: 0.5
});
return (
<div>
<svg width={100} height={100} viewBox="0 0 100 100">
<motion.path d={d} />
</svg>
<p>
<button onClick={() => cycleShape()}>TOGGLE</button>
</p>
</div>
);
}
And a demo sandbox
The "Ensure colors are of the same type" is unexpected. That should read the two values should contain the same number of numbers and colors (that are of the same type). As others have pointed out if the path changes too much you need a morpher.
I am wanting to use the same functionality to Poses SVG morphing, I try something like:
And I get an error saying:
Error: Complex values 'M255,0C114.75,0,0,114.75,0,255s114.75,255,255,255s255-114.75,255-255S395.25,0,255,0z' and 'M510,255c0-20.4-17.85-38.25-38.25-38.25H331.5L204,12.75h-51l63.75,204H76.5l-38.25-51H0L25.5,255L0,344.25h38.25 l38.25-51h140.25l-63.75,204h51l127.5-204h140.25C492.15,293.25,510,275.4,510,255z' too different to mix. Ensure all colors are of the same type. at invariant (hey-listen.es.js:11)
Can Framer Motion support SVG morphing yet?
Cheers!