HTML Canvas中心缩放脉冲动画位置偏移问题求解
解决Canvas缩放后矩形中心偏移问题
问题根源
- 中心坐标计算错误:原代码误将大矩形左上角坐标的一半当作中心,实际大矩形中心应为左上角坐标加上自身尺寸的一半。
- 缩放平移逻辑错误:
setTransform的平移参数未正确抵消缩放带来的位移,导致中心偏移。 - 小矩形绘制锚点错误:直接基于大矩形左上角偏移绘制,未以中心为锚点,缩放后位置偏离。
修正后的代码
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
相关产品推荐
相关产品推荐

