如何通过转换检测哪个元素悬停在 CanvasRenderingContext2D 上?

问题描述 投票:0回答:1

我有一个画布,在上面应用了一些变换(主要是平移将原点放在中间和缩放比例)。我现在想知道光标是否悬停在画布上绘制的元素上。

检测非常简单:“光标距对象中心的距离是否小于 n 屏幕像素”。

如何获取已应用变换的元素的屏幕坐标?

这是我到目前为止所得到的:我做了很长的路,当我应用其他转换(例如缩放)时,它不适合。

在以下示例中,黄色方块以

(0;0)
为中心,但由于
ctx.translate()
而显示在屏幕中间。

const ctx = canv.getContext('2d')
ctx.fillRect(0, 0, canv.width, canv.height)

ctx.translate(canv.width / 2, canv.height / 2)

ctx.fillStyle = 'yellow'
ctx.fillRect(-4, -4, 8, 8) // centered at (0,0)

canv.addEventListener('mousemove', event => {
  const dX = canv.width / 2 - event.offsetX
  const dY = canv.height / 2 - event.offsetY
  const distance = Math.sqrt(dX * dX + dY * dY)
  coord.innerText = `Distance to square: ${distance}`
})
<canvas id="canv"></canvas>
<div id="coord"></div>

有没有更干净的方法来实现这一目标?

javascript html5-canvas matrix-transform
1个回答
0
投票
const elements = []

// Draw elements 
const rect = {
  x: 100, 
  y: 50, 
  width: 50,
  height: 80
}

ctx.translate(50, 100)
ctx.rotate(Math.PI / 4)
ctx.fillRect(rect.x, rect.y, rect.width, rect.height)

elements.push({
  ...rect,
  transform: ctx.getTransform()  
})

function checkHover(mouseX, mouseY) {

  // Inverse transform mouse pos
  const invertedMousePos = {
    x: mouseX,
    y: mouseY
  }
  invertTransform(invertedMousePos, ctx.getTransform().invertSelf())

  // Check if mouse pos intersects any element 
  for (let el of elements) {
    if (invertedMousePos.x > el.x && 
        invertedMousePos.y > el.y &&
        invertedMousePos.x < el.x + el.width &&
        invertedMousePos.y < el.y + el.height) {
      return el
    }
  }

  return null
}
© www.soinside.com 2019 - 2024. All rights reserved.