You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求基于鼠标位置的Canvas游戏Tilemap缩放数学公式

基于鼠标位置锚定的Tilemap缩放实现方案

我正好做过类似的功能,这其实是锚点缩放的经典应用——核心目标就是让鼠标指向的地图位置,在缩放前后始终停留在屏幕的同一位置,而不是单纯粗暴地增减缩放值和偏移量。咱们一步步拆解逻辑:

核心数学逻辑步骤

先明确几个关键变量:

  • currentScale:Tilemap当前的缩放比例(x/y方向一致的话用一个值就行)
  • mouseScreenX/mouseScreenY:鼠标在屏幕上的坐标
  • tilemapPosX/tilemapPosY:Tilemap当前的左上角偏移像素位置
  • newScale:缩放后的目标比例(比如滚轮向上放大1.1倍,向下缩小到0.9倍)
  1. 把屏幕鼠标坐标转成Tilemap本地原始坐标
    这个坐标是Tilemap未缩放、无偏移时,鼠标对应的真实位置,公式是:

    localMouseX = (mouseScreenX - tilemapPosX) / currentScale
    localMouseY = (mouseScreenY - tilemapPosY) / currentScale
    

    简单说就是:先把鼠标相对于Tilemap左上角的像素距离,除以当前缩放比例,得到未缩放时的原始位置。

  2. 计算缩放后的新偏移量
    缩放后要保证localMouseX * newScale + 新偏移量 = mouseScreenX,变形后得到:

    newTilemapPosX = mouseScreenX - localMouseX * newScale
    newTilemapPosY = mouseScreenY - localMouseY * newScale
    

    这一步就是让鼠标指向的原始位置,在新缩放比例下,刚好落在屏幕的鼠标坐标处。

  3. 应用新的缩放和偏移
    把计算出的newScale和newTilemapPosX/Y赋值给Tilemap对应属性即可。

适配你的RPG Maker代码实现

结合你给出的代码,修改后的wheel_函数可以这样写(适配RPG Maker的坐标单位逻辑):

const SM_S = SceneManager._scene;
const tilemap = SM_S._spriteset._tilemap;
const zoomSpeed = 1.1; // 每次滚轮的缩放倍数,比加减0.05更平滑自然
const minZoom = 0.3; // 最小缩放比例
const maxZoom = 3; // 最大缩放比例

function wheel_(event) {
    event.preventDefault(); // 阻止页面默认滚动行为

    const currentScale = tilemap.scale.x;
    let newScale = currentScale;

    // 确定缩放方向与目标比例
    if (event.wheelDeltaY > 0) {
        newScale = Math.min(currentScale * zoomSpeed, maxZoom);
    } else {
        newScale = Math.max(currentScale / zoomSpeed, minZoom);
    }

    if (newScale === currentScale) return; // 达到缩放边界就停止处理

    // 获取鼠标屏幕坐标(RPG Maker内置方法)
    const mouseScreenX = Input.mouseX();
    const mouseScreenY = Input.mouseY();

    // 把Tilemap的tile单位偏移转成像素单位
    const tileWidth = $gameMap.tileWidth();
    const tileHeight = $gameMap.tileHeight();
    const tilemapPosX = $gameMap._displayX * tileWidth;
    const tilemapPosY = $gameMap._displayY * tileHeight;

    // 计算鼠标在Tilemap的原始本地坐标
    const localMouseX = (mouseScreenX - tilemapPosX) / currentScale;
    const localMouseY = (mouseScreenY - tilemapPosY) / currentScale;

    // 计算新的像素偏移,再转成tile单位赋值给游戏地图
    const newTilemapPosX = mouseScreenX - localMouseX * newScale;
    const newTilemapPosY = mouseScreenY - localMouseY * newScale;
    $gameMap._displayX = newTilemapPosX / tileWidth;
    $gameMap._displayY = newTilemapPosY / tileHeight;

    // 应用新缩放比例
    tilemap.scale.x = newScale;
    tilemap.scale.y = newScale;
}

额外注意点

  • 用倍数缩放代替固定增减值,缩放体验更自然,也更容易控制边界
  • RPG Maker里的_displayX/Y是tile单位,必须和像素单位转换后再计算,不然会出现偏移错误
  • 添加缩放边界限制,避免过度缩放导致显示异常

内容的提问来源于stack exchange,提问作者jon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:47:38