我有一个画布,在上面应用了一些变换(主要是平移将原点放在中间和缩放比例)。我现在想知道光标是否悬停在画布上绘制的元素上。
检测非常简单:“光标距对象中心的距离是否小于 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>
有没有更干净的方法来实现这一目标?
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
}