返回
在 object-fit: contain 中将鼠标位置转换为画布坐标:解决鼠标事件坐标不匹配
javascript
2024-05-25 02:40:56
在 object-fit: contain 下将鼠标位置转换为画布坐标
简介
当使用 object-fit: contain
属性时,画布会调整大小以适合其容器。虽然这很方便,但会导致鼠标事件位置与画布坐标不匹配。本文将探讨如何解决此问题,以及如何计算 letterboxing(画布周围的空白区域)的尺寸。
问题
当使用 object-fit: contain
时,鼠标事件位置覆盖了包括 letterboxing 在内的整个区域。因此,无法直接将事件位置转换为画布坐标,因为 letterboxing 会影响位置。
解决方案
要将事件位置转换为画布坐标,我们需要减去 letterboxing 的尺寸:
-
计算 letterboxing 尺寸:
letterboxWidth = imageWidth - canvasWidth
letterboxHeight = imageHeight - canvasHeight
-
计算画布坐标:
canvasX = eventX - letterboxWidth / 2
canvasY = eventY - letterboxHeight / 2
通过使用这些公式,我们可以获得与事件位置相匹配的画布坐标。
示例
让我们修改前面的示例以解决这个问题:
canvas.onmousemove = (e) => {
// 计算 letterboxing 的尺寸
const letterboxWidth = imageWidth - canvas.width
const letterboxHeight = imageHeight - canvas.height
// 计算画布坐标
const canvasX = e.offsetX - letterboxWidth / 2
const canvasY = e.offsetY - letterboxHeight / 2
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.strokeRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(canvasX,canvasY, 10, 0, 2 * Math.PI);
ctx.stroke();
pt.innerText=`${canvasX}x${canvasY}`;
}
现在,圆形和鼠标指针将在画布的所有位置匹配。
常见问题解答
-
为什么
object-fit: contain
会导致这个问题?object-fit: contain
调整画布的大小以适合其容器,这意味着画布的尺寸可能与图像不同。这会导致 letterboxing,从而影响鼠标事件位置。
-
我可以使用
getBoundingClientRect()
吗?- 否,
getBoundingClientRect()
获取元素相对于视口的边界框,它不受object-fit
的影响。
- 否,
-
如果图像的宽高比与容器的宽高比不同怎么办?
- 在这种情况下,画布的尺寸仍应使用
min()
函数计算,但可能会在水平或垂直方向上出现 letterboxing。
- 在这种情况下,画布的尺寸仍应使用
-
可以使用 JavaScript 监听
resize
事件吗?- 是的,如果您期望容器的大小发生变化,这可能是必要的。然而,它可能会产生额外的开销,并且在某些情况下可能不实用。
-
是否可以在不使用 JavaScript 的情况下解决这个问题?
- 否,
object-fit
是一个 CSS 属性,它仅受浏览器处理。在不使用 JavaScript 的情况下,无法动态计算 letterboxing 的尺寸。
- 否,
结论
解决 object-fit: contain
下鼠标位置和画布坐标不匹配的问题涉及计算 letterboxing 的尺寸并减去这些尺寸。通过使用本文提供的公式,您可以在所有情况下获得准确的画布坐标。