JSFiddle - React, Tailwind, and code Playground

by Roman Bruckner

HTML

<button id="button">Send token</button>

<svg
  width="100%"
  height="100%"
  viewBox="0 0 500 300"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
>
  <!-- Draw the outline of the motion path in blue, along
                      with three small circles at the start, middle and end. -->
  <path
    id="path1"
    d="M100,250 C 100,50 400,50 400,250"
    fill="none"
    stroke="blue"
    stroke-width="7.06"
  />
</svg>

JavaScript

function sendTokenAlongPath(pathId, duration, color) {
  // SVG Circle element
  const pathEl = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "circle",
  )
  pathEl.classList.add("animated-path")
  pathEl.setAttribute("r", "20")
  pathEl.setAttribute("fill", color)
  pathEl.setAttribute("stroke", "red")

  // SVG Animate motion element
  const animateMotionEl = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "animateMotion",
  )
  animateMotionEl.setAttribute("dur", `${duration}ms`)
  animateMotionEl.setAttribute("repeatCount", "1")
  animateMotionEl.setAttribute("calcMode", "linear")
  animateMotionEl.setAttribute("fill", "freeze")
  animateMotionEl.setAttribute("keyPoints", "0;1")
  animateMotionEl.setAttribute("keyTimes", "0;1")

  const motionPathEl = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "mpath",
  )
  motionPathEl.setAttribute("href", `#${pathId}`)
  animateMotionEl.appendChild(motionPathEl)

  pathEl.appendChild(animateMotionEl)
  document.querySelector("svg").appendChild(pathEl)

  animateMotionEl.beginElement()

  setTimeout(() => {
    pathEl.parentNode.removeChild(pathEl)
  }, duration)
}

// Send a token along the path every 4 seconds.
// The token is stuck at the start of the path and does not move in Chrome.
setInterval(() => {
  sendTokenAlongPath("path1", 2000, "green")
}, 4000)

// Send a token along the path when the button is clicked.
// The token works as expected in Chrome.
document.getElementById("button").addEventListener("click", () => {
  sendTokenAlongPath("path1", 2000, "yellow")
})