First, below is the desired result without any JavaScript added
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body { display: flex; justify-content: center; align-items: center; }
svg { width: 12.5rem; height: 6rem; }
path { fill: none; stroke: #444; stroke-width: 5px; }
circle { opacity: 0.75; fill: #0dd; }
<svg>
<path
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z"
/>
<circle r='10'>
<animateMotion
dur="5s" repeatCount="indefinite"
path="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z"
/>
</circle>
</svg>
Notice the animateMotion
element and values of the path
attribute. Everything works perfectly in the snippet above.
In the snippet below, however, we don't have the path
attribute yet added on the animateMotion
element so we're trying to insert it with JavaScript. In the completed program the path
attribute will be filled with dynamic values.
Why doesn't the animateMotion
element work here like in the first snippet when the DOM structure is identical?
let animateMotion = document.querySelector( `animateMotion` );
animateMotion.setAttributeNS(
`http://www.w3.org/2000/svg`, `path`,
`M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z`
);
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body { display: flex; justify-content: center; align-items: center; }
svg { width: 12.5rem; height: 6rem; }
path { fill: none; stroke: #444; stroke-width: 5px; }
circle { opacity: 0.75; fill: #0dd; }
<svg>
<path
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z"
/>
<circle r='10'>
<animateMotion
dur="5s" repeatCount="indefinite"
/>
</circle>
</svg>
Upon inspection we can see the browser appears to have correctly added the path
attribute exactly as it appears in the HTML of the first snippet:
Try passing null as the namespace
in setAttributeNS
let animateMotion = document.querySelector( `animateMotion` );
animateMotion.setAttributeNS(
null, `path`,
`M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z`
);
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body { display: flex; justify-content: center; align-items: center; }
svg { width: 12.5rem; height: 6rem; }
path { fill: none; stroke: #444; stroke-width: 5px; }
circle { opacity: 0.75; fill: #0dd; }
<svg>
<path
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z"
/>
<circle r='10'>
<animateMotion
dur="5s" repeatCount="indefinite"
/>
</circle>
</svg>