title: Why is pointerdown event delivered to a wrong PIXI.Container after scaling containers up and down? Test case attached
body: <p>I have a custom class called <code>Tile</code> extending <a href="https://pixijs.download/v5.3.3/docs/PIXI.Container.html" rel="nofollow noreferrer">PIXI.Container</a>.</p>
  <p>It is instantiated three times and stored in the variables: <code>r</code>, <code>g</code> and <code>b</code>.</p>
  <p>First I drag the 3 tiles around, horizontally (i.e. keeping the tiles in the 4th row):</p>
  <p><a href="https://i.stack.imgur.com/IjKxf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IjKxf.png" alt="screenshot 1" /></a></p>
  <p>And after some time, when I click the <strong>middle</strong> tile, then wrongly the <code>onDragStart</code> method of the <strong>left</strong> tile is called (in the screenshot below you can see that I have clicked the blue tile, but the green has been raised):</p>
  <p><a href="https://i.stack.imgur.com/7DWWW.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7DWWW.png" alt="screenshot 3" /></a></p>
  <p>So the <code>pointerdown</code> event is called on the wrong object!</p>
  <p>I have a feeling that the root cause for this is that the <code>Tile</code> objects are scaled up when clicked and thus Pixi.js thinks that it should deliver the event to the still big object.</p>
  <p>But I haven't been able to come up with a fix or a workaround yet.</p>
  <p>Below is the complete and simple test case for my issue.</p>
  <p>The bug is always reproducible for me, just move the tiles around 5-10 times and you will be able to see it.</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function Tile(color, onDragStart, onDragMove, onDragEnd, x, y) {
      PIXI.Container.call(this);
  
      this.x = x;
      this.y = y;
  
      this.interactive = true;
      this.buttonMode = true;
      this.on('pointerdown', onDragStart)
          .on('pointermove', onDragMove)
          .on('pointerup', onDragEnd)
          .on('pointerupoutside', onDragEnd);
  
      this.graph = new PIXI.Graphics();
      this.graph.beginFill(color);
      this.graph.drawRect(0, 0, Tile.W, Tile.W);
      this.graph.endFill();
      this.addChild(this.graph);
      this.cacheAsBitmap = true;
  }
  
  Tile.W = 100;
  Tile.prototype = Object.create(PIXI.Container.prototype);
  Tile.prototype.constructor = Tile;
  
  Tile.prototype.startDragging = function() {
      this.scale.x = 1.6;
      this.scale.y = 1.6;
      this.alpha = 0.8;
  };
  
  Tile.prototype.stopDragging = function() {
      this.scale.x = 1;
      this.scale.y = 1;
      this.alpha = 1;
      // align x, y to the checker board grid
      this.x = Tile.W * Math.floor((this.x + Tile.W / 2) / Tile.W);
      this.y = Tile.W * Math.floor((this.y + Tile.W / 2) / Tile.W);
  };
  
  var app = new PIXI.Application({
      width: Tile.W * 8,
      height: Tile.W * 8,
      view: document.getElementById('pixiCanvas'),
      backgroundColor: 0xFFFFFF
  });
  
  var background = new PIXI.Graphics();
  for (var i = 0; i &lt; 8; i++) {
      for (var j = 0; j &lt; 8; j++) {
          if ((i + j) % 2 == 0) {
              background.beginFill(0xCCCCFF);
              background.drawRect(i * Tile.W, j * Tile.W, Tile.W, Tile.W);
              background.endFill();
          }
      }
  }
  app.stage.addChild(background);
  
  var r = new Tile(0xFF0000, onDragStart, onDragMove, onDragEnd, 3 * Tile.W, 3 * Tile.W);
  var g = new Tile(0x00FF00, onDragStart, onDragMove, onDragEnd, 4 * Tile.W, 3 * Tile.W);
  var b = new Tile(0x0000FF, onDragStart, onDragMove, onDragEnd, 5 * Tile.W, 3 * Tile.W);
  
  app.stage.addChild(r);
  app.stage.addChild(g);
  app.stage.addChild(b);
  
  function onDragStart(ev) {
      this.data = ev.data;
      var pos = this.data.getLocalPosition(this.parent);
      this.x = pos.x - this.width / 2;
      this.y = pos.y - this.height / 2;
      // put the tile on top
      app.stage.removeChild(this);
      app.stage.addChild(this);
      this.startDragging();
  }
  
  function onDragMove() {
      if (this.data) {
          var pos = this.data.getLocalPosition(this.parent);
          this.x = pos.x - this.width / 2;
          this.y = pos.y - this.height / 2;
      }
  }
  
  function onDragEnd() {
      if (this.data) {
          var pos = this.data.getLocalPosition(this.parent);
          this.data = null;
          // the next 2 lines are not needed here, but 
          // in my real game I put the tile beneath the HUD
          app.stage.removeChild(this);
          app.stage.addChildAt(this, app.stage.children.length);
          this.stopDragging();
      }
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>#pixiCanvas {
        width: 100%;
        height: 100%;
        background: #CCF;
        box-sizing: border-box;
        border: 4px red dotted;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;canvas id="pixiCanvas"&gt;&lt;/canvas&gt;
  &lt;script src="https://cdn.jsdelivr.net/npm/pixi.js@5.3.7/dist/pixi.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdn.jsdelivr.net/npm/pixi.js-legacy@5.3.7/dist/pixi-legacy.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>
  <p>Additionally I have created <a href="https://github.com/pixijs/pixi.js/issues/7233" rel="nofollow noreferrer">issue 7233</a> at Github and you can also see the bug in <a href="https://wordsbyfarber.com" rel="nofollow noreferrer">my real app</a>:</p>
  <p><a href="https://i.stack.imgur.com/jMAsj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jMAsj.png" alt="app screenshot" /></a></p>
  <p><strong>Things I have tried sofar, which haven't helped:</strong></p>
  <ul>
  <li>Switching <code>Tile</code> base class from <code>PIXI.Container</code> to <code>PIXI.Sprite</code></li>
  <li>Moving <code>startDragging</code> and <code>stopDragging</code> calls before <code>removeChild</code> and <code>addChild(At)</code></li>
  <li>Removing <code>removeChild</code> and <code>addChild(At)</code> calls completely</li>
  <li>Removing <code>this.scale.x = 1.6</code> and <code>this.scale.y = 1.6</code></li>
  <li>Searching for <a href="https://github.com/pixijs/pixi.js/search?q=pointerdown" rel="nofollow noreferrer">pointerdown</a> at Pixi.js repo (do not understand the source code)</li>
  </ul>