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

仅通过位置与尺寸实现Canvas元素缩放功能的技术求助

Canvas 指定中心点缩放实现(不使用内置scale/translate)

要实现围绕Canvas上指定点的缩放,且仅通过修改元素的位置和尺寸完成,核心是让元素的位置偏移量和尺寸同步按缩放比例调整。

核心位置计算逻辑

对于每个元素,缩放后的位置需要基于原始位置与缩放中心点的相对偏移来计算:

  • 先算出元素原始位置到缩放中心点的水平/垂直距离
  • 这个距离乘以缩放级别,得到缩放后的偏移量
  • 最后加上缩放中心点的坐标,就是元素新的位置

公式如下:

rect.x = zoom.x + (rect.originalX - zoom.x) * zoom.level;
rect.y = zoom.y + (rect.originalY - zoom.y) * zoom.level;

补全后的完整代码

JavaScript 部分

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const canvasW = canvas.width;
const canvasH = canvas.height;

// 模拟图像的矩形元素,保存原始位置和尺寸
var rects = [
    {
        originalX:10,
        x:10,
        originalY:10,
        y:10,
        originalW:25,
        w:25,
        originalH:25,
        h:25,
        color:'blue'
    },
    {
        originalX:90,
        x:90,
        originalY:40,
        y:40,
        originalW:65,
        w:65,
        originalH:35,
        h:35,
        color:'red'
    },
    {
        originalX:80,
        x:80,
        originalY:120,
        y:120,
        originalW:30,
        w:30,
        originalH:30,
        h:30,
        color:'pink'
    },
    {
        originalX:180,
        x:180,
        originalY:190,
        y:190,
        originalW:45,
        w:45,
        originalH:35,
        h:35,
        color:'green'
    }
];

// 缩放配置:中心点、级别、方向
var zoomData = {
    x:150, // 缩放中心点(这里是Canvas中心)
    y:150,
    level: 1, // 1为原始大小,>1放大,<1缩小
    direction: 1 // 1放大,-1缩小
};

function draw(){
    ctx.clearRect(0, 0, canvasW, canvasH);

    // 绘制背景
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, canvasW, canvasH);

    // 绘制所有矩形
    for(var rect of rects){
        ctx.fillStyle = rect.color;
        ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
    }

    // 绘制缩放中心点标记
    ctx.fillStyle = 'white';
    ctx.fillRect(zoomData.x - 5/2, zoomData.y - 5/2, 5, 5);

    // 执行缩放逻辑
    Zoom(rects,zoomData);

    // 自动切换缩放方向
    if(zoomData.level<=0.5){
        zoomData.direction = 1;
    } else if(zoomData.level>=1.5){
        zoomData.direction = -1;
    }
    zoomData.level+=0.01*zoomData.direction;

    requestAnimationFrame(draw);
}

// 补全后的缩放函数
function Zoom(rects,zoom){
    for(var rect of rects){
        // 计算缩放后的位置
        rect.x = zoom.x + (rect.originalX - zoom.x) * zoom.level;
        rect.y = zoom.y + (rect.originalY - zoom.y) * zoom.level;
        // 计算缩放后的尺寸
        rect.w = rect.originalW * zoom.level;
        rect.h = rect.originalH * zoom.level;
    }
}

requestAnimationFrame(draw);

HTML 部分

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Canvas Zoom Rectangles</title>
</head>
<body>
    <canvas id="canvas" width="300" height="300"></canvas>
</body>
</html>

原理说明

  • 所有元素始终基于原始位置计算缩放后的位置,避免多次缩放导致的偏移误差
  • 缩放时,元素与中心点的相对距离同步缩放,保证围绕中心点放大/缩小的效果
  • 尺寸直接用原始尺寸乘以缩放级别,和位置计算逻辑保持一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:45:25