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
相关产品推荐
相关产品推荐

