I have a problem where two of my svg have the same number of points, but something isn't right when I play the animation, the two svgs are so close together but the animation just jumps out of nowhere and it isn't right, a weird shape happens before the first svg changes to the second.
I'm doing the svgs in Adobe XD. Here is the code:
<svg id="morph" viewBox="0 0 1920 540">
<path class="morph" d="m864.216 135.95 36.39 41.917S780.519 307.11 1078.914 373.479s221.979-87.327 221.979-87.327l32.75-34.931s25.473 101.3 207.422 34.931 440.314 150.2 411.2 380.744S34.528 576.079 34.528 576.079s-3.64-429.647 342.063-509.987 272.923 174.653 487.623 69.861"/>
</svg>
<script>
var overlay = document.getElementById('morph');
var morphing = anime({
targets: '.morph',
d: [
{value : "m864.216 135.95 36.39 41.917S780.519 307.11 1078.914 373.479s221.979-87.327 221.979-87.327l32.75-34.931s25.473 101.3 207.422 34.931 440.314 150.2 411.2 380.744S34.528 576.079 34.528 576.079s-3.64-429.647 342.063-509.987 272.923 174.653 487.623 69.861"},
{value: "M2.49 576.483S20.535 398.736 122.472 239.61s236.674-199.127 302-217.883c176.407-41.244 334 45.685 334 45.685l340 233.7s172 105.427 280 119.484 322 12.3 322 12.3 118 5.271 160 61.5 56 89.613 62 117.727S2.49 576.483 2.49 576.483Z"},
],
duration: 1200,
loop: false,
easing: 'easeInOutQuint'
})
</script>
Your paths still need some optimizations to be fully compatible for interpolation.
Most animation libraries try to make paths compatible to some extent (e.g by converting them to polygons like in flubber.js).
But usually you'll get the best results cleaning up your paths manually.
Your command types also need to be compatible.
E.g. The second animation step has only one
l(lineTo) command and aZ(closePath) missing in the first path.Unfortunately, you can't be sure your editor/graphic app will output the same commands as it might decide to use shorthand commands (like h for horizontal lineTos )to minify the markup.
Normalize
dto a reduced set of commandsThis will simplify the further adjustments by converting path data to M, C, L and Z commands.
I'm using Jarek Foksa's getPathData polyfill.
{normalize: true}Parameter will also convert all commands to absolute coordinates.Convert L commands to C
You can easily convert
Lcommands toCcurves by repeating the x/y coordinates like this.to:
Adjust
Mstarting pointsSet the starting point to something like the leftmost corner/point. So your paths will be interpolated using a visual reference point. Otherwise you might get weird flipping transitions.
Changing the
Mof a path is also way easier with absolute and normalized commands. You'll also find a helper function in the snippet(1. path data chunk => will be appended after the second chunk)
M 864 136 (old starting point => will be deleted)
C 901 178 901 178 901 178
C 901 178 781 307 1079 373
C 1377 440 1301 286 1301 286
C 1334 251 1334 251 1334 251
C 1334 251 1359 353 1541 286
C 1723 220 1981 436 1952 667
C 1923 897 35 576 35 576 => will become the new M xy coordinate
(2. path data chunk)
C 35 576 31 146 377 66
C 722 -14 650 241 864 136
(3. path data chunk: closePath)
Z
Result:
Path direction
In your case both paths have a clockwise direction.
If you encounter weird flipping transitions you can try to reverse path directions.
You might use @enxaneta's great codepen example or Svg Path commander Library.
Example 1: Normalize and change starting point (including helpers)
Example 2: morph optimized paths with anime.js
... Quite a lot of work.
But once your paths are super compatible you can also morph between shapes via plain css. (E.g by animating/transitioning
d:path()properties).