skip to Main Content

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


  1. Your new <path> is placed: x: 64.961 y:-15.355 (first 2 values after m)

    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.

    svg{
      border: 1px solid red;
      width:20em;
      overflow:visible
    }
    <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <path id="circlePath" d="M25.67 79.86a34.98 34.41 90 0 1 0-49.47a34.98 34.41 90 0 1 48.67 0a34.98 34.41 90 0 1 0 49.47" fill="none" stroke-linecap="round" pathLength="100" />
      </defs>
      <use href="#circlePath" stroke="#D3D7DB" stroke-width="4" />
      <use href="#circlePath" stroke="#008000" stroke-width="6" stroke-dasharray="50 100" />
      <circle cx="0" cy="0" r="6" stroke-width="6" fill="#FFFFFF" stroke="#008000">
        <animateMotion fill="freeze" begin="0s" dur="0s" repeatCount="0" keyPoints="0.5;0.5"  keyTimes="0;1" calcMode="linear">
          <mpath xlink:href="#circlePath" />
        </animateMotion>
      </circle>
    </svg>

    You could also define your horseshoe path as a reusable element within <def> an reference it via <use> and <mpath>.

    Login or Signup to reply.
    1. 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.

    2. You should take the time to understand how the <animateMotion> works. It animates the circle, moving it from the first value of keyPoints to the second during the duration of the animation. The attribute dur has the value infinite, which is simply invalid. Instead, the initial value indefinite is used. Since there is also no end 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 of keyPoints to the same.

    3. Currently, your stroke-dasharray="0 270" draws a zero-length dash (visible as a circle because of stroke-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" and keyPoints="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.

    <body>
        <svg
          #svgRoot
          id="svgclick"
          version="1.1"
          viewBox="0 0 79.375 79.375"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g transform="rotate(90)" >
            <path
              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
              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="270 270"
              stroke-dashoffset="243"
              id="thumb"
            />
            <circle
              cx="0"
              cy="0"
              r="6"
              stroke-width="6"
              fill="#FFFFFF"
              stroke="#008000"
            >
              <animateMotion
                begin="0s"
                dur="0s"
                repeatCount="infinite"
                keyPoints="0.1;0.1"
                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>
          </g>
        </svg>
      </body>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search