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

如何在Lua网格画布插件中实现鼠标位置中心缩放

问题描述

我正在用Lua为程序插件开发自定义画布,画布上绘制了方格网格,缩放通过控制方格宽度实现,共有7级缩放(缩小切换到更高层级,放大切换到更低层级)。相机用一个相对于(0,0)的xy偏移点cameraOffset来控制平移。

当前代码里,缩放时画布是围绕(0,0)点进行的,仅方格尺寸和绘制位置p会变化。现在需要在保留网格系统的前提下,实现围绕鼠标位置的缩放效果。

现有代码如下:

-- 每个索引对应一个缩放级别,Lua索引从1开始。如果用户缩放超出边界,会被限制在边界内
local squareSizes = {8, 12, 16, 20, 24, 28, 32}
local squareSizeIndex = 3 -- 用户缩放时会外部修改这个值
local cameraOffset = {x=0, y=0} -- 用户平移屏幕时会修改这个值

local function drawSquare(x, y, size)
    -- 绘制方格的占位函数:在指定xy位置绘制指定尺寸的方格
end

local function Update(squares, mousePos) -- mousePos格式和cameraOffset一致(比如mousePos.x是鼠标x坐标)
    for p, _ in pairs(squares) do -- p是方格应该绘制的位置,会随方格尺寸变化,因为到下一个p所需的像素数会变
        local x = p.x + cameraOffset.x
        local y = p.y + cameraOffset.y
        drawSquare(x, y, squareSizes[squareSizeIndex])
    end
end
解决方案

要实现围绕鼠标缩放,核心是在缩放时调整相机偏移量cameraOffset,让鼠标位置对应的世界网格点在屏幕上保持固定。具体实现如下:

核心逻辑步骤

  1. 触发缩放时,先获取缩放前后的方格尺寸(oldSize和newSize)
  2. 根据鼠标当前屏幕坐标,计算新的相机偏移量,确保鼠标对应的网格点在缩放后仍处于屏幕原位置
  3. 更新缩放级别并应用新的偏移量

修改后的完整代码

-- 每个索引对应一个缩放级别,Lua索引从1开始。如果用户缩放超出边界,会被限制在边界内
local squareSizes = {8, 12, 16, 20, 24, 28, 32}
local squareSizeIndex = 3 -- 用户缩放时会触发handleZoom来修改这个值
local cameraOffset = {x=0, y=0} -- 用户平移屏幕时会修改这个值

local function drawSquare(x, y, size)
    -- 绘制方格的占位函数:在指定xy位置绘制指定尺寸的方格
end

-- 处理缩放逻辑:delta为+1(缩小,切换到更高层级)或-1(放大,切换到更低层级)
local function handleZoom(delta, mousePos)
    local oldIndex = squareSizeIndex
    -- 限制缩放级别在1到7之间
    local newIndex = math.max(1, math.min(#squareSizes, oldIndex + delta))
    if newIndex == oldIndex then return end -- 已到边界,无需处理
    
    local oldSize = squareSizes[oldIndex]
    local newSize = squareSizes[newIndex]
    
    -- 计算新的相机偏移量,确保鼠标位置对应的网格点固定在屏幕上
    cameraOffset.x = mousePos.x - ((mousePos.x - cameraOffset.x) * newSize / oldSize)
    cameraOffset.y = mousePos.y - ((mousePos.y - cameraOffset.y) * newSize / oldSize)
    
    -- 更新缩放级别
    squareSizeIndex = newIndex
end

local function Update(squares, mousePos) -- mousePos格式和cameraOffset一致(比如mousePos.x是鼠标x坐标)
    for p, _ in pairs(squares) do -- p是方格应该绘制的位置,会随方格尺寸变化,因为到下一个p所需的像素数会变
        local x = p.x + cameraOffset.x
        local y = p.y + cameraOffset.y
        drawSquare(x, y, squareSizes[squareSizeIndex])
    end
end

关键逻辑说明

  • 缩放前先通过(mousePos - cameraOffset) / oldSize计算出鼠标屏幕坐标对应的网格世界坐标
  • 缩放后,要让这个世界坐标对应的屏幕坐标仍等于原鼠标位置,因此推导出新偏移量公式:newOffset = mousePos - worldPos * newSize
  • 代入世界坐标表达式后,就得到了代码中调整cameraOffset的计算方式

这样修改后,缩放操作会围绕鼠标位置进行,同时完全保留原有的网格系统和相机平移逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 08:43:21