Reputation: 139
I'm trying to morph an SVG of a circle (converted to a path in Illustrator using Object > Compound Path > Make) into an square (converted the same way) using Anime.js but when the timeline runs, the circle shape is distorted as if the path is not being interpreted properly.
The square shape looks fine though.
As a test, you can remove the target class of shape
from the SVG in the markup to prevent Anime.js from running and the circle will appear correctly.
Why is Anime.js unable to read my circle?
const circlePath = 'M153.1,49.5c63.2,0,114.5,51.3,114.5,114.5s-51.3,114.5-114.5,114.5S38.6,227.2,38.6,164S89.9,49.5,153.1,49.5z';
const squarePath = 'M270.7,275.7H23.9V31h246.8V275.7z';
var timeline = anime.timeline({
autoplay: true,
direction: "alternate",
loop: true
});
timeline.add({
targets: ".shape",
d: {
value: [
circlePath,
squarePath
],
duration: 1500,
easing: "easeInOutQuad"
},
offset: 1500
});
svg {
margin: 1rem;
border: 2px solid #666;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="300px" height="300px" viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<path class="shape" fill="blue" d="M153.1,49.5c63.2,0,114.5,51.3,114.5,114.5s-51.3,114.5-114.5,114.5S38.6,227.2,38.6,164S89.9,49.5,153.1,49.5z"/>
</svg>
Upvotes: 1
Views: 1532
Reputation: 14545
To perform smooth morphing from one shape to another, several conditions must be met
You can get paths that meet these requirements using any vector editor.
Let's say you want to realize smooth morphing a circle into a rectangle
Draw a circle in the vector editor
Add four more points along the diagonals, they will be needed to shift the contour of the circle into a square
Save the file in * .svg format and copy the path
to another file. This will be the initial figure for morphing.
Next, drag these four anchor points to the corners of the square and adjust the control points of the anchor points (blue arrows in the figure)
Save the file again in the vector editor and copy the second path
it will be the final morph figure
Substitute path
for the initial and final elements in your application:
const circlePath = 'm268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z';
const squarePath = 'm268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z';
var timeline = anime.timeline({
autoplay: true,
direction: "alternate",
loop: true
});
timeline.add({
targets: ".shape",
d: {
value: [
circlePath,
squarePath
],
duration: 1500,
easing: "easeInOutQuad"
},
offset: 500
});
svg {
margin: 1rem;
border: 2px solid #666;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="300px" height="300px" viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<path class="shape" fill="blue" d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z"/>
</svg>
The most difficult thing was to get the correct path
formulas. Having them, you can implement morphing without using Javascript using pure SVG
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="300" height="300" viewBox="0 0 300 300" >
<style>
path {
fill:dodgerblue;
stroke:none;
}
</style>
<path d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z" stroke="black" fill="dodgerblue">
<animate attributeName="d"
begin="0s"
dur="3s"
values="
m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;
m268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z"
repeatCount="indefinite"
fill="freeze"
/>
</path>
</svg>
Reverse movement
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="300" height="300" viewBox="0 0 300 300" >
<style>
path {
fill:dodgerblue;
}
</style>
<path d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z">
<animate attributeName="d"
begin="0s"
dur="5s"
values="
m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;
m268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z;
m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;"
repeatCount="indefinite"
fill="freeze" />
</path>
</svg>
Smooth morphing animation can also be done with SnapJS
var svg = document.getElementById("svg1");
var s = Snap(svg);
var simpleCup = Snap.select('#coffee-cup');
var fancyCup = Snap.select('#fancy-cup');
var simpleCupPoints = simpleCup.node.getAttribute('d');
var fancyCupPoints = fancyCup.node.getAttribute('d');
var toFancy = function(){
simpleCup.animate({ d: fancyCupPoints }, 1000, mina.backout, toSimple);
}
var toSimple = function(){
simpleCup.animate({ d: simpleCupPoints }, 1000, mina.backout, toFancy);
}
toSimple();
<svg id="svg1" width="100" height="130" viewBox="0 0 75 47" xmlns="http://www.w3.org/2000/svg">
<path id="coffee-cup" fill="#5F0C2D" stroke="#5F0C2D" d="M0.4 5.9C0.4 6.3-0.3 17.8 4.3 31.2 5.3 32.4 6.1 37.9 7.5 43 10.4 53.6 10 58.2 10 58.2 10 58.2 10 59.1 10 62.2L10 63.4 15 65.7C20.1 67.8 34 67.6 38.6 65.7L44 64 44 62.2C44 60.3 44 61.2 44 59.6 44 59.6 44 58.2 44 58.2 44 58.2 44 56 44 56 44 56.1 44.2 52.2 44.2 52.2 44.2 52.2 44.5 49.3 44.5 49.3 44 47 46.8 39.1 47.6 38.8 48.4 38.6 52.8 37.6 55.4 37 62.3 36.7 68.5 30.5 68.5 26.9 68.5 25.1 68.5 20.3 66.1 17.8 63.5 14.8 60.4 14.1 56.7 14.2 54.2 14.3 54.2 12.8 54 12.6 53.8 12.5 54 12.6 54 10.8L53.3 6.7 51.3 4.6C49.8 3.6 47.5 3 44.7 2.2 38.3 0.5 20.1 0 12.7 1.4 7 2.4 0.4 4.7 0.4 5.9ZM64.8 22.9C64.8 25.9 65.5 27.9 60.6 31.8 59.6 32.6 64 30.3 62.9 30.8 60.9 31.9 53.6 32.7 52.4 31.8 51.6 31.1 51.1 29.8 51 28 51.3 24.6 52.1 22.1 53.6 20.4 57.4 16 64.8 19.2 64.8 22.9Z" />
<path opacity="0" id="fancy-cup" fill="#5F0C2D" stroke="#5F0C2D" d="M0 6.8C0 7.2 0.9 8.5 1.9 9.6 2.9 10.8 4.9 15.9 6.3 21 9.2 31.6 12.4 36.5 17.5 38.2 21.6 39.6 21.7 39.8 18.8 42.2L16.5 44 19.5 45.3C24.6 47.4 37 47.6 41.6 45.7L45.5 44.1 43.1 42.1C41 40.4 40.9 39.9 42.1 39.1 42.8 38.6 44.2 38.2 45.1 38.2 47 38.2 52.4 33.5 53.2 31.2 53.6 29.9 53.9 29.9 55.3 31 57.5 32.9 59.1 31.6 58.4 28.6 58 27 58.3 26.1 59.1 25.8 59.9 25.6 62.6 24.8 65.2 24.2 70.7 22.7 75 19 75 15.5 75 13.7 74.1 12.7 71.3 11.6 68 10.2 67.3 10.2 63.7 11.6 61.4 12.5 59.5 13 59.3 12.8 59.1 12.7 59.9 11.3 61 9.9L63.1 7.3 60.5 5.6C59 4.6 55.5 3.2 52.7 2.4 46.3 0.7 21.5-0.1 14.1 1.3 8.4 2.3 0 5.6 0 6.8ZM70 15.6C70 18.6 65.7 22.2 62.3 22.2 61 22.2 59 22.7 57.9 23.2 55.9 24.3 55.5 23.6 56.6 20.8 56.9 19.9 57.6 19.5 58.1 19.8 58.6 20.1 60.5 18.7 62.2 16.8 66 12.4 70 11.9 70 15.6Z" />
</svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
Upvotes: 9