takopus

Pointer events missing for sprites in masked container

Recommended Posts

I've found some strange behavior in interactivity events of display object inside a masked container. Not sure if this is a bug or just a questionable decision; anyway, it poses some problems.

Generally interactive display objects receives events such as "pointermove" or "pointerupoutside" at any time, whether pointer is over them or not. Same applies to masked display objects, by the way. But if you place an interactive display object inside a masked container, events fire only when pointer is over masked area. All events, including "pointerupoutside", so there's no way to keep track of pointer position and button state. Look at this codepen.

Have anyone faced this problem? I guess I can assign event listeners to the stage container or nearest parent without mask, and it will probably work, but seems a little bit dirty to me. Is there a better solution?

Share this post


Link to post
Share on other sites

Ok, gonna share my own solution. Kinda dirty, but working. Hope this will help someone.

First, add this little helper to DisplayObject. It will return nearest parent which is not inside a masked container (but can have mask, which is irrelevant):

PIXI.DisplayObject.prototype.getNearestUnmaskedParent = function(){
    var parents = [];
    var dobj = this;
    while (dobj.parent){
        dobj = dobj.parent;
        parents.unshift(dobj);
    }
    for (var i=0, l=parents.length; i<l; i++){
        if (parents[i].mask) return parents[i];
    }
    return this;
};

 

And now if you need to add event listeners to a display object inside a masked container, do it like this:

this.onPointerDown = function(){
	// get unmasked parent:
	this.unmaskedParent = this.myInteractiveObject.getNearestUnmaskedParent();
  
	// store it's interactivity state and set it to true:
	this.unmaskedParentInteractivity = this.unmaskedParent.interactivity;
	this.unmaskedParent.interactivity = true;
  
	// set your event listeners:
	this.unmaskedParent.on("pointerupoutside", this.onPointerUp, this);
}

this.onPointerUp = function(){
	this.unmaskedParent.removeListener("pointerupoutside", this.onPointerUp, this);
  
	// restore parent interactivity and forget it:
	this.unmaskedParent.interactivity = this.unmaskedParentInteractivity;
	delete this.unmaskedParent;
	delete this.unmaskedParentInteractivity;
}

this.myInteractiveObject.on("pointerdown", this.onPointerDown, this);

 

Share this post


Link to post
Share on other sites

I think that's the cause: https://github.com/pixijs/pixi.js/blob/v4.x/src/interaction/InteractionManager.js#L1045

I added that `else` and i certainly didnt think about pointer events and stuff like `trackedPointers`.

Unfortunately, I already have too many issues on me, I can only recommend to look at my old try at fixing interaction: https://github.com/pixijs/pixi-display/blob/layers/src/InteractionManagerMixin.ts#L19

Maybe if you add pixi-layers plugin in the project it'll help :) (that's the repo i mentioned)

If you have an idea on how to fix that easily in vanilla pixijs you can submit PR for pixi version v4 (v4.x branch) or for v5 (dev branch, default).

Share this post


Link to post
Share on other sites

I fear I have no required knowledge in PIXI or actually JS to dig into all of this.

And, sadly, my solution above helps with only a half of the problem. Now I can watch pointer movement, but I can't get "pointerupoutside" event. I catch "pointerdown" on some DisplayObject (scrollbar, actually) and add "pointerupoutside" on any of it's parents. But since said parent had not received "pointerdown" before, "pointerupoutside" won't fire.

It seems to me that right solution may be simple: any listener, subscribed to "*move" and "*upoutiside" events must get them, regardless of hit test. If you have a minute to spare, could you please stick my nose to place in sources where I can try to make an override for this?

Thanks for your help anyway!

Share this post


Link to post
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...

  • Recently Browsing   0 members

    No registered users viewing this page.