fabricjs / fabric.js

Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser
http://fabricjs.com
Other
29.06k stars 3.51k forks source link

[Bug]: Impossible to resize object when added as clippath #9392

Open apliez opened 1 year ago

apliez commented 1 year ago

CheckList

Version

6.0.0-beta9

In What environments are you experiencing the problem?

Firefox Chrome Microsoft Edge

Node Version (if applicable)

None

Link To Reproduction

https://jsfiddle.net/y4am7h1w/29/

Steps To Reproduce

  1. Create an object
  2. Add as clippath
  3. Impossible to resize it

Expected Behavior

The shape should be resizable because the controls are available

Actual Behavior

The shape cannot be resized

Error Message & Stack Trace

No error messages
asturur commented 1 year ago

Is unclear what is your desired end goal. Are you trying to implement image cropping?

ShaMan123 commented 1 year ago

Also, forgive me barging in, you provided a repro not the the version you reported...

apliez commented 1 year ago

Is unclear what is your desired end goal. Are you trying to implement image cropping?

I simplified the fiddle but imagine the red background is the same image blurred with filter. I want to cut the image in multiple parts (group clippath) to see the image without filter. All of this is functionnal in my app but I don't know why use clippath block resizing, skewing and rotation on shape used as clippath.

Also, forgive me barging in, you provided a repro not the the version you reported...

I don't understand why you say this, the version link used in fiddle is https://cdn.jsdelivr.net/npm/fabric@6.0.0-beta9/dist/index.min.js

ShaMan123 commented 1 year ago

Sorry, my bad about the repro version

asturur commented 1 year ago

can you take a screenshot of this all and how the image should look like?

gloriousjob commented 1 year ago

Typically, our clippath demos have the image draggable and the clippath static. In the op's case, the image is static (i.e., not selectable) and the clippath is draggable. When you click on the clippath rectangle, it shows controls but they don't work (you can drag the rectangle though, just not scale/rotate it). Not sure if a dynamic clippath is expected functionality.

gloriousjob commented 1 year ago

Actually, if there's a bug here, it's that sendObjectToBack actually showed the image even though it's never added to the canvas.

@apliez Please add the canvas.add(image); and canvas.add(background); calls before the sendObjectToBack calls...

ShaMan123 commented 1 year ago

I think I understand what you want. You want an interactive rect to clip your image.

This is a feature I POCed #7879

The problem is that you are using the rect in 2 different planes. First you add it to canvas (@gloriousjob has revealed an unexpected behavior - an object is added to canvas when calling sendObjectTo/FromXXX) Then you assign it as the image clip path. The clip path exists in the image plane. Since your image it not transformed it is only the translation of the plane that is different from the canvas plane. That is why the controls are wrong and that is why in v6 we introduced a strict object tree concept. We need to enforce it on clip paths as well but that is too messy with how freely clip paths can be assigned to an object. You also need rendering context isolation because you don't want to clip the red bg. So I suggest you group the image and the clipping rect. This will allow both requirements: rendering context isolation (group own cache) and clipping rect interactivity (group interactivity)

The fiddle almost accomplished everything The only thing is that when selecting the clipping rect the rendering context isolation is not respected for a reason I didn't figure out yet, canvas.preserveObjectStacking should have taken care of that. https://jsfiddle.net/8hLpfct9/2/

ShaMan123 commented 1 year ago

My demo also reveals that the rotation control should use set to invalidate the cache of the group Try rotating the clipping rect and see

ShaMan123 commented 1 year ago

Thinking of it cropping controls seem an overkill with this small example cropX/Y can be easily obtained by the relative position offset and updated accordingly @iocoker I believe this is the fastest and easiet solution you are looking for

ShaMan123 commented 1 year ago

This is even better https://jsfiddle.net/u9eL85r3/

iocoker commented 1 year ago

Many thanks @ShaMan123, actually we do have the clipping implemented with the new Group V6. This works with an existing shape, like a rect, a star or any shape that we someone can place a picture into. That works fine.

https://github.com/fabricjs/fabric.js/assets/81635623/b0392f0b-ef75-4b81-a3df-c02147faf586

The cropping we needed is for standalone image like this:

https://github.com/fabricjs/fabric.js/assets/81635623/c72c55ab-2cb7-4290-9452-a1b3fa705369

@asturur Any hope you will release the cropping feature you have? Or @ShaMan123's one, if there's anything we can do to hasten this?

ShaMan123 commented 1 year ago

I prefer the first ux... And it is very simple to build in v6 so my products are moving on with that

gloriousjob commented 12 months ago

@iocoker it sounds like your bug is resolved by doing the expected functionality (add the image before sending it to back). I'm not sure I understand the feature you want though. The clipping that you showed is how fabric handles things. You seem to have a particular use case and I don't really understand how the image is moving and resizing in your demo. I'd think you'd have custom code to handle move and scale events so that the image would be adjusted accordingly.

jialan0229 commented 6 months ago

Many thanks @ShaMan123, actually we do have the clipping implemented with the new Group V6. This works with an existing shape, like a rect, a star or any shape that we someone can place a picture into. That works fine.

Recording.2023-11-07.143845.1.mp4 The cropping we needed is for standalone image like this:

Recording.2023-11-07.144511.mp4 @asturur Any hope you will release the cropping feature you have? Or @ShaMan123's one, if there's anything we can do to hasten this?

Hello, may I ask how this method is implemented