question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Trying to manipulate SVG "d" values causes error

See original GitHub issue

I am wanting to use the same functionality to Poses SVG morphing, I try something like:

const boxVariants = {
  initial: {
    fill: "pink",
    d:
      "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",
  },
  hover: {
    fill: "pink",
    d:
      "M255,0C114.75,0,0,114.75,0,255s114.75,255,255,255s255-114.75,255-255S395.25,0,255,0z",
  },
}

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!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:8
  • Comments:6

github_iconTop GitHub Comments

8reactions
kevinwolfcrcommented, Jan 16, 2021

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

4reactions
zambocommented, May 15, 2020

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

Read more comments on GitHub >

github_iconTop Results From Across the Web

Here's How I Solved a Weird Bug Using Tried and True ...
At first, this looks like a CSS issue. Some styles might be applied on a hover event that breaks the layout or the...
Read more >
Python svgwrite Drawing Error "not a valid value for attribute 'd ...
I try to extract one path from a SVG ...
Read more >
5 Most Common Problems Faced by SVG Users - Vecta.io
Your SVG namespace is not declared properly causing the SVG image to be displayed incorrectly. Quick fix: Check and fix your SVG namespaces....
Read more >
svg arc path command parsing error on sweep flag
This means that if the user is trying to understand what is wrong with a path by experimentation, and the path has a...
Read more >
Fills and Strokes - SVG: Scalable Vector Graphics | MDN
Using fill sets the color inside the object and stroke sets the color of the line drawn around the object. You can use...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found