svgdotjs / svg.js

The lightweight library for manipulating and animating SVG
https://svgjs.dev
Other
10.97k stars 1.07k forks source link

Set clip path to element that is not added to root yet. #1256

Closed SebastianStehle closed 10 months ago

SebastianStehle commented 2 years ago

Feature request

At the moment I can easily add clip paths to element that are part of the SVG document. But if I add a clip path to an element that has not been added yet it throws an extension because the .def() property is undefined.

I would like to add clip paths to elements that are not added yet. Because I create svg elements first and then I would like to add them.

Benefits

If it does not work, a good error message would be better than an exception.

Fuzzyma commented 2 years ago

Yeah error messages are nice but if we would check all cases where a user can use the API wrongly, the lib would be twice as big and half as fast :D. I agree that it is not optimal tho. To answer the question: it is not possible the way you wanna do it but still totally doable. Just create a clippath element, add it to the defs yourself (whenever you are ready) and use el.clipWith(clippath).

const clipPath = new SVG.ClipPath()
clipPath.circle(100)

const toBeClipped = canvas.rect(100, 100)
toBeClipped.clipWith(clipPath)

// once you attach your svg
defs.add(clipPath)
SebastianStehle commented 2 years ago

Yes, I have solved it, the happens when I use something like the following.

const clipPath = new SVG.ClipPath()
clipPath.circle(100)

const toBeClipped = new SVG.Rect();
toBeClipped.clipWith(clipPath) // Throws exception.

// once you attach your svg
defs.add(clipPath)

Your example should work fine or at least should not throw. The problem is that the toBeClipped is not part of the root.

Fuzzyma commented 2 years ago

Are you sure? Because looking at the code, it would just set an attribute on the rect, nothing else. Only if you use clipWith with a different element then clipPath it might throw an error

SebastianStehle commented 2 years ago

Like this to be precise:

const toBeClipped = new SVG.G();
toBeClipped.clipWith(clipPath) // Throws exception.

EDIT: I was wrong, I also fixed another bug, that was probably causing the issue. I am a little bit confused now.