In this question the author of the question is able to position an SVG circle on top of a path like this:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
</svg>
</div>
I’ve noticed that if I change the first keyPoints
value it moves the circle. This is a stackblitz containing the same markup in case anyone wants to play with it.
I’d like to apply this approach to a different path.
<path
#thumb
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="0 270"
stroke-dashoffset="-260"
id="thumb"
/>
And I assumed it would just be a matter of copying in the circle markup:
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
And then changing the path
attribute value from M20,60a35,35 0 1,1 60,0
to m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6
, however this ends up placing the circle on top of the SVG path and almost out of focus.
<body>
<svg
#svgRoot
id="svgclick"
version="1.1"
viewBox="0 0 79.375 79.375"
xmlns="http://www.w3.org/2000/svg"
>
<path
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="10.583"
/>
<path
#thumb
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="0 270"
stroke-dashoffset="-260"
id="thumb"
/>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.1;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
></animateMotion>
</circle>
</svg>
</body>
Thoughts?
2
Answers
Your new
<path>
is placed: x: 64.961 y:-15.355 (first 2 values afterm
)That’t why you path is almost off-canvas.
Since your path is already relative, you only need to change these 2 values to change the x/y offset in your viewBox.
You can also rotate the path
d
directly using svg path editor.You could also define your horseshoe path as a reusable element within
<def>
an reference it via<use>
and<mpath>
.The
transform
attribute is quite simply not applied to the motion path. Wrap the paths and the circle in a<g transform="rotate(90)">
, remove the attributes from the individual paths, and all vectors will be positioned collectively.Applying that transform attribute to the
<circle>
element will not work. That would only rotate the circle in place around its center. The motion path would be applied in the un-rotated coordinate system.You should take the time to understand how the
<animateMotion>
works. It animates the circle, moving it from the first value ofkeyPoints
to the second during the duration of the animation. The attributedur
has the valueinfinite
, which is simply invalid. Instead, the initial valueindefinite
is used. Since there is also noend
value, interpolation of values is turned off, you see no motion, and the first value is used at all times. That is what you intended, but I would think it preferable to stay with a valid combination of values and set both values ofkeyPoints
to the same.Currently, your
stroke-dasharray="0 270"
draws a zero-length dash (visible as a circle because ofstroke-linecap="round"
) and a gap of the path length. I suspect you intended to draw a partial path instead from the start of the path to the dot position. For that use:stroke-dasharray="270 270"
.Also,
stroke-dashoffset="-260"
andkeyPoints="0.1;0.1"
do not match. While the keyPoints go from 0…1, the dashoffset has to move from 270…0. So the correct value for the offset is 270 * (1 – 0.1) = 243.