Broken? ClipPath, clip-path, DOM.element("svg:svg"), and svg literal

My goal is to create a semi-ellipse by drawing an ellipse that is clipped vertically to show only the right half.

I cannot get DOM.element(“svg:svg”) to work with clipPath like the template literal. Help appreciated.

For code, please see Experiment with sliders at top and bottom of notebook to see effects. Top slider (moonFraction) works as appropriate.

function moon() uses “svgsvg…” works as expected.

function noot() uses “DOM.element(“svg:svg”…)” fails to properly use the clipPath.

I have read and understood and used

The only difference I can see in the generated DOM is that the latter generates a “<g clipPath=…”, while the former generates a “<g clip-path=…”.

I don’t know if the difference is important or how to fix it.

Help very much appreciated.

There were two errors in your code:

const clipper = defs.appendChild(DOM.element("clipPath", {id:}));

is missing the namespace:

const clipper = defs.appendChild(DOM.element("svg:clipPath", {id:}));

, and

const g = canvas.appendChild(DOM.element("svg:g", { clipPath: showRightHalf }));

defines a property name instead of attribute:

const g = canvas.appendChild(DOM.element("svg:g", { 'clip-path': showRightHalf }));
1 Like

Here’s a working one:

@mootari already listed the issues involved.

1 Like

To add to the above, whenever I encounter misbehaving HTML elements my workflow for spotting differences is as follows:

  1. Inspect each element and copy its outerHTML.
  2. Paste the markup into an editor and autoformat it. This ensures that indentation and linebreaks will be identical.
  3. Diff both snippets, either via an editor function or manually by comparing them line by line.

Thank you very much @mootari and @jrus. It fixed the problem.

I’ve cleaned up the code and made it reusable (importable).

Give it a try on Observable » Martien » Moon Phases.

Next, I will read up on SVG and its context. Good reading tips on that for me are very much welcomed.