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

Canvas技术咨询:如何让正方形绕中心旋转后保持指定位置?

Canvas实现图形绕自身中心旋转的正确方式

我需要用Canvas实现图形(本文以正方形为例)绕自身中心旋转的效果,要求正方形初始位置在(10,16)时,旋转180度后仍停留在(10,16),且朝向向下。我尝试了几种方法,但都没达到预期,测试代码如下:

测试代码

HTML

<p>
Move your mouse to rotate the square
</p>
<p>
Select your test method via the dropdown
</p>
<select id="testMethod">
  <option value="0">Test 1</option>
  <option value="1">Test 2</option>
  <option value="2">Test 3</option>
  <option value="3">Test 4</option>
  <option value="4">Test 5</option>
</select>
<button onclick="rotateAmount = 0">Reset Rotation</button>
<br>
<canvas id="canvas" width="250" height="250"></canvas>

CSS

canvas{
  border-color: violet;
  border-style: solid;
  border-width: 5px;
}

JavaScript

const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const size = 50
const pos = canvas.width/4
let rotateAmount = 0;

const tests = [
  // Test 1
  (rotation)=>{
    ctx.translate(pos/2+size, pos/2+size)    
    ctx.rotate(Math.PI / 180 * rotation)
    ctx.fillRect(pos, pos, size, size)
  },
  // Test 2
  (rotation)=>{
    ctx.translate(size/2+pos, size/2+pos)    
    ctx.rotate(Math.PI / 180 * rotation)
    ctx.fillRect(pos, pos, size, size)
  },
  // Test 3
  (rotation)=>{
    ctx.translate(pos/2, pos/2)    
    ctx.rotate(Math.PI / 180 * rotation)
    ctx.fillRect(pos, pos, size, size)
  },
  // Test 4
  (rotation)=>{
    ctx.translate(size/2, size/2)    
    ctx.rotate(Math.PI / 180 * rotation)
    ctx.fillRect(pos, pos, size, size)
  },
  // Test 5
  (rotation)=>{
    ctx.translate(pos + 0.5 * size, pos + 0.5 * size)    
    ctx.rotate(Math.PI / 180 * rotation)
    ctx.fillRect(pos, pos, size, size)
  }
]

window.onmousemove = (mouse) => {
    ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  rotateAmount++
  tests[document.getElementById("testMethod").value](rotateAmount)
}

问题分析

所有测试方法的核心问题是:旋转后绘制矩形的坐标没有做反向偏移。Canvas的变换是基于当前坐标系叠加的:当你把原点平移到正方形中心后旋转,再用原坐标(pos, pos)绘制矩形,相当于在新坐标系的(pos, pos)位置绘制,这就导致正方形偏离了原本的中心位置。

正确实现方法

要实现图形绕自身中心旋转且位置不变,正确的流程是:

  • 重置画布变换,避免每次绘制的变换叠加
  • 将坐标系原点平移到图形的中心(即初始位置X + 图形宽度/2,初始位置Y + 图形高度/2)
  • 执行旋转操作
  • 以新原点为中心绘制图形,也就是绘制坐标设为-size/2, -size/2,这样图形的中心刚好和新原点重合(对应原图形的中心位置)

修正后的完整代码

HTML

<p>
移动鼠标旋转正方形
</p>
<button onclick="rotateAmount = 0">重置旋转角度</button>
<br>
<canvas id="canvas" width="250" height="250"></canvas>

CSS

canvas{
  border-color: violet;
  border-style: solid;
  border-width: 5px;
}

JavaScript

const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const size = 50
// 题目要求的初始位置(10,16)
const posX = 10
const posY = 16
let rotateAmount = 0;

const rotateAroundCenter = (rotation) => {
  // 重置画布变换
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  
  // 平移到正方形中心
  ctx.translate(posX + size/2, posY + size/2)
  // 旋转(转换为弧度)
  ctx.rotate(Math.PI / 180 * rotation)
  // 以新原点为中心绘制正方形
  ctx.fillRect(-size/2, -size/2, size, size)
}

window.onmousemove = () => {
  rotateAmount++
  rotateAroundCenter(rotateAmount)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:15:40