Jump to content

How to handle events in PIXI?


Sebi
 Share

Recommended Posts

My problem is, that I have handlers that I got to apply to the stage itself and handlers that have to be applied to sprites.

Now if i click the sprite, the stage click is also fired.

 

How can I avoid this?

 

// edit

Okay I have just tested something.

I've created a transparent texture and used it for a sprite, set the width and height of my stage, then applied the click handler to that sprite instead of my stage. This does work as intended. Can I achieve the same goal without using an extra sprite?

 

// edit 2

here an example: http://www.mokgames.com/pixi/events/

If you click the text on the left stage, the stage click handler also fires,

if you click the text on the right stage, the stage click handler does not fire ( <- thats the one i want ) 

Link to comment
Share on other sites

actually I had a lot of troubles with events hooked to the stage, especially with touch events.

 

Anyway it should work if you put the stage event listener at the end and then stop propagation. That would work on DOM, but maybe pixi just checks for collisions and do not respect event bubbling. Give it a shot anyway.

Link to comment
Share on other sites

  • 3 months later...

So events do not bubble up the scene graph right now. However there is a review-in-progress for an implementation of this:

 

https://github.com/GoodBoyDigital/pixi.js/pull/665

 

That would fix issues like #625 that you linked.

 

Thank you for the link and the event bubbling is working quite nice, couldn't find any issue yet. Are you also planning to implement event capturing (bottom to top) with Event Target as well? Because with the current InteractionManager, I cannot stop its propagation as OP's issue without workaround nor I can find related code that does the job. 

Link to comment
Share on other sites

Thank you for the link and the event bubbling is working quite nice, couldn't find any issue yet. Are you also planning to implement event capturing (bottom to top) with Event Target as well? Because with the current InteractionManager, I cannot stop its propagation as OP's issue without workaround nor I can find related code that does the job. 

 

Probably not going to implement a separate capturing/bubbling phase but hopefully bubbling will handle most of the use cases. We understand the interaction manager is a sore point in pixi right now and definitely needs a rewrite.

Link to comment
Share on other sites

Probably not going to implement a separate capturing/bubbling phase but hopefully bubbling will handle most of the use cases. We understand the interaction manager is a sore point in pixi right now and definitely needs a rewrite.

 

Thanks for the quick reply! Can't wait for fully implemented event feature, and it actually meets most of my use cases. Just a quick question about what you meant by 'the scene graph', you mean it's not bubbling up all the layers on stage? 

 

What I've tested was this simple thing.

 

doTUqtL.png

 

yellow - Stage

red - Sprite1

blue - Sprite2

 

PIXI.EventTarget.mixin(PIXI.DisplayObjectContainer.prototype);

 

sprite2.click = function (e) {

    sprite2.dispatchEvent('click', e);

}

 

stage.addEventListener('click', function(e){console.log('stage clicked');});

sprite1.addEventListener('click', function(e){console.log('sprite1 clicked');});

sprite2.addEventListener('click', function(e){console.log('sprite2 clicked');});

 

 

then when i click on the blue it drops (or not implemented) the sprite1 (red) but Stage listens the event.

 

was it what you meant?

 

 

And also if that is done, would the way to use your bubble event be to attach its mouse events to glass layer on the top of everything and emit as they get called? Question got a bit long. I really appreciate PIXI.js as I use it together with Ejecta and Leaflet. I look forward to becoming a real contributor!

Link to comment
Share on other sites

Pixi.js is a scene graph. Nodes have children, that have children. When I say "bubbles up the scene graph" I mean an event emitted on an object will then emit from it's parent, then it's parent's parent, etc. Until there are no more parents or stopPropagation() is called.

 

Assuming red is a child of yellow, and blue is a child of red. Clicking on blue should emit the click event on blue, then red, then yellow.

Link to comment
Share on other sites

Pixi.js is a scene graph. Nodes have children, that have children. When I say "bubbles up the scene graph" I mean an event emitted on an object will then emit from it's parent, then it's parent's parent, etc. Until there are no more parents or stopPropagation() is called.

 

Assuming red is a child of yellow, and blue is a child of red. Clicking on blue should emit the click event on blue, then red, then yellow.

 

Oh yes, that's right I understand it now. Somehow I thought red is blue's parent since it's under blue layer haha.

 

actually the use case I'm doing here is exactly same as OP's work.

 

HJx7TFC.png

 

now without red, 

yellow - Stage

blue - Sprite

 

and I have these 3 cases

1. blue gets clicked and both blue's and yellow's listeners are called

2. blue gets clicked and both blue's and stop propagation

3. yellow gets clicked and yellow's listener is called

 

to Achieve case 1 and 2

 

blue.addEventListener('click', function (originalEvent) {

  blue.dispatchEvent('click', originalEvent);

}

 

yellow.addEventListener('click', function (e) {console.log('yellow clicked');});

// for case 1

blue.addEventListener('click', function (e) {console.log('blue clicked');});

// for case 2

blue.addEventListener('click', function (e) {console.log('blue clicked'); e.stopPropagation();});

 

and it'll do the job.

but to achieve case 3, I also need an emitter attached to the yellow but if I click on the blue then the result will be

 

yellow clicked

blue clicked

yellow clicked

 

I was spending hours and hours to get this through without the need of removing emitter from yellow when required and adding it again but still no luck. Would there be a better way you could suggest? Thank you very much for your time!

Link to comment
Share on other sites

I just did it in a very hacky way. 

 

I created a glass layer that is DisplayObjectContainer on the very top of everything. 

 

then set the hitArea of the layer as its Stage's size then defined an array to keep all other interactive objects.

 

glass._items = [];

glass._items.push(stage);

glass._items.push(sprite1);

glass._items.push(sprite2);

 

glass.click = function (e) {

    var im = glass.stage.interactionManager

    for (i = glass.length - 1; i >= 0; i--) {

        if (im.hitTest(glass._items, im.mouse) {

            glass._items.emit('click', e);

            return;

        }

    }

}

 

stage.addEventListener('click', do something);

sprite1.addEventListener('click', do something);

 

now I can bubble up to the object's top parent and stop propagation as I need.

 

Altho I would love to have a flawless way but think this could do the job. 

Please advise me if you guys have a better solution!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...