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

HTML Canvas中心缩放脉冲动画位置偏移问题求解

解决Canvas缩放后矩形中心偏移问题

问题根源

  1. 中心坐标计算错误:原代码误将大矩形左上角坐标的一半当作中心,实际大矩形中心应为左上角坐标加上自身尺寸的一半。
  2. 缩放平移逻辑错误:setTransform的平移参数未正确抵消缩放带来的位移,导致中心偏移。
  3. 小矩形绘制锚点错误:直接基于大矩形左上角偏移绘制,未以中心为锚点,缩放后位置偏离。

修正后的代码

const canvas = document.createElement("canvas");
canvas.setAttribute("width", "500px");
canvas.setAttribute("height", "500px");
const ctx = canvas.getContext("2d");
const wrapper = document.getElementsByClassName("wrap")[0];
wrapper.appendChild(canvas);
let scale = 1;
let angle = 0;
const blockSize = 45; // 大矩形尺寸
const pos = {x: 2, y: 1}; // 矩形位置


function anim(){
   ctx.clearRect(0, 0, canvas.width, canvas.height);
   ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置变换
   draw(ctx, pos)
   update();
   requestAnimationFrame(anim);
}
anim();

function draw(ctx, position){
    // 绘制大矩形
    ctx.fillStyle = "#000";
    const bigRectX = position.x * blockSize - blockSize;
    const bigRectY = position.y * blockSize - blockSize;
    ctx.fillRect(bigRectX, bigRectY, blockSize, blockSize);

    // 绘制带脉冲动画的小矩形
    ctx.fillStyle = "red";
    const recSize = 30;
    // 计算大矩形的中心(即小矩形的目标中心)
    const centerX = bigRectX + blockSize / 2;
    const centerY = bigRectY + blockSize / 2;

    // 设置缩放变换:以中心为基准缩放,平移量抵消缩放位移
    ctx.setTransform(scale, 0, 0, scale, centerX * (1 - scale), centerY * (1 - scale));
    // 以中心为锚点绘制小矩形(负半宽实现中心对齐)
    ctx.fillRect(centerX - recSize/2, centerY - recSize/2, recSize, recSize);
    
    ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置变换
}

function update(){
    angle += Math.PI / 140;
    scale = 0.5 + Math.abs(Math.cos(angle));
}
<div class="wrap"></div>

关键修正点说明

  • 正确计算中心:centerX = bigRectX + blockSize/2,确保拿到大矩形的实际中心坐标。
  • 缩放平移公式:centerX*(1 - scale)是核心,当缩放比例小于1时,这个值为正,将图形向中心方向平移;大于1时为负,同样抵消缩放带来的偏移,保证中心位置不变。
  • 中心锚点绘制:通过centerX - recSize/2设置小矩形的左上角,让小矩形始终以目标中心对齐,缩放时不会偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:50:12