4

I'm using Pixi JS and detecting the mouse position via a simple event handler:

...

var stage = new PIXI.Container();
stage.interactive = true;

var handler = function(e){
  mouseX = renderer.plugins.interaction.mouse.global.x;
  mouseY = renderer.plugins.interaction.mouse.global.y;
}

stage.on("pointermove", handler);

...

However mouseX and mouseY are being updated when the mouse is outside of the stage bounds (the <canvas> element on the page). Is it possible to limit the mousemove event to within the stage?

I've tried stage.hitArea but that didn't work.

SalutBarbu
  • 386
  • 5
  • 16

3 Answers3

5

This seems to be the intended behavior; calling the mousemove callback even when the mouse pointer is outside of the container is necessary for implementing certain things, for example drag&drop.

But you can keep track of whether the pointer is above the object using mouseover and mouseout events like this:

...
var graphics = new PIXI.Graphics();
graphics.hitArea = new PIXI.Rectangle(0, 0, 100, 100);
graphics.interactive = true;
stage.addChild(graphics);
...

var mouseIn = false;
graphics.on("mouseover", function(e) {
  console.log("over")
  mouseIn = true;
});

graphics.on("mouseout", function(e) {
  console.log("out");
  mouseIn = false;
});

graphics.on("mousemove",function(e) {
  if (mouseIn) {
    console.log("mouse move inside", e)
  }
});

(NOTE: I couldn't get mouseout and mouseover events firing on the stage object - but apparently you should only add child elements to the stage and interact with them. Also, the hitArea is necessary.)

This JSFiddle should demonstrate this idea, see the console output: http://jsfiddle.net/qc73ufbh/

It really seems to be feature rather than a bug, checkout these closed issues on this topic: https://github.com/pixijs/pixi.js/issues/2310 and https://github.com/pixijs/pixi.js/issues/1250

emanek
  • 411
  • 2
  • 8
  • Thank you for the detailed response! This appears to be the correct way to do it. I guess `mouseout` and `mouseover` don't work on the stage object because it covers the whole browser viewport. Thanks again :-) – SalutBarbu Jul 04 '17 at 09:45
1

It can be easily accomplished by setting the moveWhenInside property of interaction manager

app.renderer.plugins.interaction.moveWhenInside = true;

var app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);

app.renderer.plugins.interaction.moveWhenInside = true;

 const myGraph = new PIXI.Graphics();
    myGraph.interactive = true;
    myGraph.buttonMode = false;

    myGraph.on('pointermove', (evt) => {
        console.log('pointermove',evt.data.global.x, evt.data.global.y);
    });
    
    
    app.stage.addChild(myGraph);
    myGraph.beginFill(0xFFFFFF);
    myGraph.drawCircle(100, 100, 50);
    myGraph.endFill();
0

You can check if the event target is the PIXIDisplay.DisplayObject you want to act upon.

So in the OP's example that would be:

var stage = new PIXI.Container();
stage.interactive = true;

var handler = function(e){
  if (e.target === stage) {
    mouseX = renderer.plugins.interaction.mouse.global.x;
    mouseY = renderer.plugins.interaction.mouse.global.y;
  }
}

stage.on("pointermove", handler);
AbbaJee
  • 1
  • 2
  • Please provide an explanation to your code - it is very hard to understand something when it isn't explained. Read - https://stackoverflow.com/help/how-to-answer – ethry Jul 02 '22 at 21:27