Search code examples
javascriptcanvasmousetileisometric

Canvas - Isometric view by transform, determine which tile is mouse on


I'm trying to make actual hover on tiles when the canvas is transformed.

Problem image

What is working

The render function:

ctx.save()
ctx.transform(1, 0.5, -1, 0.5, 250, 150)
// ctx.setTransform(1, 0.5, -1, 0.5, 250, 150)

Terrain.forEach((line, lineNumber) => {
  line.forEach((tile, blockNumber) => {
    const block = new Block({
      ...resolveBlock(tile),
      position: {
        x: blockNumber * 32 + 250,
        y: lineNumber * 32
      },
      size: {
        width: 32,
        height: 32
      }
    })

    // check if the mouse position is on tile
    block.mousePos(frameNow)
    block.render()
  })
})

ctx.restore()

The mousePos function which is working on

ctx.rotate(Math.PI / 4)

but not on the full ctx.transform(...) or even ctx.scale(1, 0.5)

function mousePos() {
  let currentX =
    mousePos.x * Math.cos(-(Math.PI / 4)) -
    mousePos.y * Math.sin(-(Math.PI / 4))

  let currentY =
    mousePos.x * Math.sin(-(Math.PI / 4)) +
    mousePos.y * Math.cos(-(Math.PI / 4))

  if (
    currentX >= this.position.x &&
    currentX <= this.position.x + this.size.width - 1 &&
    currentY >= this.position.y &&
    currentY <= this.position.y + this.size.height - 1
  ) { // change color of hovered tile... }
}

Thanks for your time.


Solution

  • Found the solution after some brainstorming; find the mouse position after transform

    const invertedTransform = ctx.mozCurrentTransformInverse()
    // sadly there is no currentTransformInverse in all browsers yet
    
    const wX =
      mousePos.x * invertedTransform.a +
      mousePos.y +
      invertedTransform.c +
      invertedTransform.e
    
    const wY =
      mousePos.x * invertedTransform.b +
      mousePos.y +
      invertedTransform.d +
      invertedTransform.f