使用双上下文获取 canvas 上的真实鼠标位置

Get the real mouse location on a canvas with double context

有人要求我在 html5 使用 canvas 制作的游戏中获取鼠标坐标。 作为第一个测试,尝试使用以下函数读取鼠标位置。但是此函数仅读取鼠标位置,同时考虑到 canvas.

的尺寸

发生的事情是游戏的舞台比 canvas 大,这个功能没有显示角色在舞台上的真实位置。

我正在搜索并注意到 behind”canvas 存在于地图 (.png) 中,其像素尺寸已经确定。 canvas 像照相机一样工作,可以看到地图的一部分。

是否可以调整我的函数以读取地图的尺寸​​,然后定位玩家的实际坐标?

        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext("2d");

        canvas.addEventListener("click", function(e) { 
            var cRect = canvas.getBoundingClientRect();

            var scaleX = canvas.width / cRect.width;
            var scaleY = canvas.height / cRect.height;

            var canvasX = Math.round((e.clientX - cRect.left) * scaleX);
            var canvasY = Math.round((e.clientY - cRect.top) * scaleY);

            console.log("X: "+canvasX+", Y: "+canvasY);
        });  

这个函数只会根据canvas的大小给我鼠标的位置,但是地图更大,我在这里留下一张解释性的图片。

希望你理解我的意思。提前致谢。

世界 <=> 查看

要建立白话,使用的术语是

  • World:world/playfield/(红框)的坐标系(以像素为单位)。
  • View:canvas/camera/(蓝框)的坐标系(单位canvas像素)。

正如评论中指出的那样。您需要视图原点。也就是世界space.

中canvas左上角的坐标

您还需要了解视图比例。这就是 canvas 相对于世界的大小。

所需信息

const world = {width: 2048, height: 1024}; // Red box in pixels
const view = {  // blue box
    origin: {x: 500, y: 20},      // in world scale (pixels on world)
    scale: {width: 1, height: 1}, // scale of pixels (from view to world)
}

没有此信息,您无法进行转换。它必须存在,因为它需要将世界内容渲染到 canvas。

请注意 如果比例为 1,则只能在 canvas 渲染系统中推断。如果找不到比例尺,请使用 1.

注意这个答案假设没有旋转视图。

查看 => 世界

以下函数将从视图坐标转换为世界坐标。

function viewToWorld(x, y) { // x,y pixel coordinates on canvas
    return {
        x: x * view.scale.width + view.origin.x,
        y: y * view.scale.height + view.origin.y
    };     // return x,y pixel coordinates in world
}

在客户端为 canvas

的鼠标事件中使用
function mouseEvent(event) {
    // get world (red box) coords 
    const worldCoord = viewToWorld(event.clientX, event.clientY);

    // normalize
    worldCoord.x /= world.width;
    worldCoord.y /= world.height;
}

世界 => 查看

您可以反向转换。即通过以下函数从世界坐标移动到视图坐标。

function normalWorldToView(x, y) { // x,y normalized world coordinates
    return {
        x: (x * world.width - view.origin.x) / view.scale.width,
        y: (y * world.height - view.origin.y) / view.scale.height
    };     // return x,y pixel on canvas (view)
}

以像素为单位

function worldToView(x, y) { // x,y world coordinates in pixels
    return {
        x: (x - view.origin.x) / view.scale.width,
        y: (y - view.origin.y) / view.scale.height
    };     // return x,y pixel on canvas (view)
}