SVG.js实现对象沿路径分段变速移动的问题求助
Hey there, I’ve run into this exact issue before with SVG.js motion path animations—super frustrating when the second animation resets to the origin instead of picking up where the first left off! Let’s break down why this happens and how to fix it.
Why It’s Happening
By default, every SVG.js animate() call starts from the initial state of the element (in your case, the square’s starting position at (0,0)), not the end state of the previous animation. When you tried using move(), it probably got overwritten because motion path animations control the element’s transform under the hood, so manual position changes don’t stick for the next animation segment.
The Solution: Explicitly Set the Starting Offset for the Second Animation
The key is to tell the second animation to start from the 65% progress mark of your spiral path, not the beginning. Here’s how to do it properly with SVG.js (assuming you’re using the motionPath plugin, which is standard for path animations):
Step-by-Step Code Example
// Initialize SVG canvas const draw = SVG().addTo('body').size(600, 600); // Create your spiral path (adjust the path data to match your spiral) const spiralPath = draw.path('M300,300 C300,150 450,150 450,300 C450,450 300,450 300,300 C300,150 150,150 150,300 C150,450 300,450 300,300') .fill('none').stroke('#ddd'); // Create the square to animate const square = draw.rect(40, 40).fill('#ff4444').center(300, 300); // First animation: 8s to 65% of the path square.animate(8000) .motionPath(spiralPath, { offset: [0, 0.65] }) .after(() => { // Second animation: 2s from 65% to 100% of the path square.animate(2000) .motionPath(spiralPath, { offset: [0.65, 1] }); });
How This Works
- The first animation uses
offset: [0, 0.65]to animate from the start of the path to 65% completion over 8 seconds. - In the
after()callback (triggered when the first animation finishes), we start the second animation withoffset: [0.65, 1]—this explicitly tells SVG.js to start the animation at the 65% progress point instead of resetting to 0.
If You’re Not Using the MotionPath Plugin
If you’re using native SVG animateMotion instead of the plugin, you can achieve the same effect by setting the begin attribute to the end of the first animation, and adjusting the keyPoints/keyTimes values:
const animate1 = square.animate(8000).attr({ 'animateMotion': { path: spiralPath.attr('d'), keyPoints: '0;0.65', keyTimes: '0;1', dur: '8s', fill: 'freeze' } }); const animate2 = square.animate(2000).attr({ 'animateMotion': { path: spiralPath.attr('d'), keyPoints: '0.65;1', keyTimes: '0;1', dur: '2s', begin: animate1.id + '.end', fill: 'freeze' } });
The fill: 'freeze' ensures the element stays at the end position of each animation, and begin: animate1.id + '.end' starts the second animation right after the first finishes.
Quick Troubleshooting Tip
If you still see a jump, double-check that:
- You’re using a recent version of SVG.js (v3+ is recommended for better motion path support)
- The
motionPathplugin is installed and imported correctly (if you’re using it) - You’re not accidentally resetting the element’s position or transform anywhere else in your code
内容的提问来源于stack exchange,提问作者Sabra Ossen

