<svg viewBox="0 0 100 100" width="100%" height="100%">
<defs>
<marker id="start" viewBox="-5 -5 10 10"
markerWidth="5" markerHeight="5">
<circle r="4" fill="none" stroke="darkgray"/>
<text font-size="8" dy="0.4em"
text-anchor="middle">S</text>
</marker>
</defs>
<path id="p" d="M50 20
Q80 0 70 30 T 70 70 T 30 70 T30 30Z"
fill="none" stroke="gray"
marker-start="url(#start)"/>
<circle r="4" fill="red" fill-opacity="0.7">
<animateMotion id="forward"
dur="10s" begin="0s" fill="freeze"
keyPoints="0.3;1;0;0.3"
keyTimes="0;0.7;0.7;1"
calcMode="linear" >
<mpath xlink:href="#p"/>
</animateMotion>
<animateMotion id="backward"
begin="forward.end + 1s"
dur="10s" fill="freeze"
keyPoints="0.3;0;1;0.3"
keyTimes="0;0.3;0.3;1"
calcMode="linear" >
<mpath xlink:href="#p"/>
</animateMotion>
</circle>
<text font-size="5"><textPath xlink:href="#p" startOffset="30%" method="stretch" spacing="auto"><tspan dy="-2">Animating motion on a closed path, starting from an arbitrary point partway along the path.</tspan></textPath>
</svg>
<p> There is no pre-defined way in SVG1.1 to define an offset for <code><animateMotion></code>. However, you can mimic this behaviour by using key points and times, jumping from the end to the beginning of the path instantaneously.
</p>
<p>The math to calculate <code>keyPoints</code> and <code>keyTimes</code> for the forward movement is as follows:
<code><dl>
<dt>keyPoints</dt>
<dd>(startPosition)</dd>
<dd>1</dd>
<dd>0</dd>
<dd>(startPosition)</dd>
<dt>keyTimes</dt>
<dd>0</dd>
<dd>(1 - startPosition)</dd>
<dd>(1 - startPosition)</dd>
<dd>1</dd>
</dl></code>
For the reverse motion, it is:
<code><dl>
<dt>keyPoints</dt>
<dd>(startPosition)</dd>
<dd>0</dd>
<dd>1</dd>
<dd>(startPosition)</dd>
<dt>keyTimes</dt>
<dd>0</dd>
<dd>(startPosition)</dd>
<dd>(startPosition)</dd>
<dd>1</dd>
</dl></code>
In both cases <code>startPosition</code> is a decimal between 0 and 1 representing the proportion of distance along the path. You also need to explicitly set <code>calcMode="linear"</code> for the key values to have an effect.
</p>
<p>Now if only there was a way to get text on a path to wrap around a closed path.
body, html {
height: 100%;
}
@media (orientation: landscape) {
svg {
height: 100%;
width: 70%;
float: right;
display: block;
}
}
@media (orientation: portrait) {
svg {
height: 70%;
width: 100%;
display: block;
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.