pixijs
pixijs copied to clipboard
@pixi/events Masked container with nested child containers doesn't bubble events.
Expected Behavior
Grandchild's event listeners should work as they do with non masked grandparent.
Current Behavior
Grandchild's event listeners are not triggered if it's grandparent is masked.
Steps to Reproduce
See running example.
Create following hierarchy:
Container with mask and interactive -> Container without any event listeners or mask -- -> Displayobject with eventlistnener
Test with mask enabled: Does not work. Comment out adding mask: Does work.
Environment
pixi.jsversion: 6.1.3- Browser & Version: Chrome 94
- OS & Version: Windows 10
- Running Example: https://www.pixiplayground.com/#/edit/t5WBOFp3-SBRfYvedOxe1
I agree this seems like a bug. Thanks for the example and simple explanation @jramstedt
Seems to be working fine if you comment out these lines:
delete PIXI.Renderer.__plugins.interaction;
renderer.addSystem(PIXI.EventSystem, 'events');
Running example https://www.pixiplayground.com/#/edit/rJ34d_evdxC1k-6lZwEpB
Seems to be working fine if you comment out these lines:
delete PIXI.Renderer.__plugins.interaction;renderer.addSystem(PIXI.EventSystem, 'events');
Yes, This is a @pixi/events problem.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Any news?
It's not a bug, explanation
I've done some investigating and this is not a bug. In your code, you have the following scene graph structure:
Stage
|
Container
|
Container, Mask
| |
Button (no children)
This means the mask is like any other DisplayObject and it'll capture events passing it's hit-test if one of it's ancestors is interactive. Indeed, the mask you've added is a 75px square that's transparent and it is rendered above the red button. That's why the hitTestRecursive method returns a 0-length array on the mask (it passes hit testing but since it's not interactive, it isn't included in the propagation path of the ensuing pointerdown event):
What you can do about it!
1 − (suboptimal) Reorder your scene graph
You can reorder the children of the grandparent container, such that the mask comes before the button. This will cause the hit-testing algorithm to prioritize the button over the mask.
However, the mask will continue to capture events that happen outside the button but inside the mask.
2 − (optimal) Set visible to false on the mask
You can instead set the visible flag on the mask to false. The hit-testing algorithm will ignore these invisible objects.
I've updated the playground you've attached to this issue to demonstrate the fix.
https://www.pixiplayground.com/#/edit/t5WBOFp3-SBRfYvedOxe1
@bigtimebuddy I'm open to putting in any documentation changes needed to make this more obvious.
@ShukantPal very good and clear explanation! 👍
Thanks for the explanation. However, I would assume this to work the same way as before, otherwise migrating to new events can be laborious and error prone.
Wouldn't the "fix" just be to also check "isMask" when checking for visible in hit testing?
Oh yes, but you’d have to wait for a release
@ShukantPal I tested this with 7.1.2
Masks are not masking if visible = false.
This is still a problem. Childs of masked containers doesn't work. They don't change pointer or get events.
I found a workaround. Adding empty rectangle to mask's hitArea circumvents this problem.
this.mask.hitArea = Rectangle.EMPTY
Note: If you want to listen events in "empty" areas the masked displayobject needs hitArea to be set. This is because the mask's area aren't added to event bounds.
Hey @jramstedt
This should be fixed in 7.2.0. We now ignore masks when doing hit testing