如何对带旋转角的矩形数据结构执行水平/垂直翻转?
旋转矩形的水平/垂直翻转实现
矩形数据结构说明
我们使用如下结构描述带旋转的矩形:
{ x: number, // 左上角x坐标 y: number, // 左上角y坐标 w: number, // 矩形宽度 h: number, // 矩形高度 a: number // 绕自身中心的旋转角度(弧度) }
需求概述
需要通过修改上述矩形的参数,实现水平翻转和垂直翻转的视觉效果:
- 水平翻转:旋转后的矩形左右镜像(例如向右倾斜的矩形变为向左倾斜,整体关于垂直轴对称)
- 垂直翻转:旋转后的矩形上下镜像(例如向上倾斜的矩形变为向下倾斜,整体关于水平轴对称)
翻转的参数计算逻辑
水平翻转
水平翻转的核心是让矩形关于垂直轴对称,只需修改两个参数:
- 旋转角度取反:原角度
a变为-a,保证翻转后的旋转方向与原方向镜像 - 调整左上角x坐标:以矩形中心为基准,将原矩形的右下角x坐标映射为新的左上角x坐标,公式为:
newX = 2*(x + w/2) - (x + w)
封装成函数:
function flipHorizontally(rect) { const centerX = rect.x + rect.w / 2; return { ...rect, x: 2 * centerX - (rect.x + rect.w), a: -rect.a }; }
垂直翻转
垂直翻转的核心是让矩形关于水平轴对称,同样修改两个参数:
- 旋转角度取反:原角度
a变为-a,保证翻转后的旋转方向与原方向镜像 - 调整左上角y坐标:以矩形中心为基准,将原矩形的右下角y坐标映射为新的左上角y坐标,公式为:
newY = 2*(y + h/2) - (y + h)
封装成函数:
function flipVertically(rect) { const centerY = rect.y + rect.h / 2; return { ...rect, y: 2 * centerY - (rect.y + rect.h), a: -rect.a }; }
测试验证代码
结合提供的绘制代码,添加翻转函数并测试效果:
const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); canvas.width = 400; canvas.height = 200; // 画布旋转辅助函数 function rotateCanvas(ctx, x, y, a) { ctx.translate(x, y); ctx.rotate(a); ctx.translate(-x, -y); } // 绘制旋转矩形 function drawRotatedRectangle(ctx, rX, rY, rW, rH, rA) { rotateCanvas(ctx, rX + rW / 2, rY + rH / 2, rA); ctx.beginPath(); ctx.rect(rX, rY, rW, rH); ctx.stroke(); rotateCanvas(ctx, rX + rW / 2, rY + rH / 2, -rA); } // 水平翻转函数 function flipHorizontally(rect) { const centerX = rect.x + rect.w / 2; return { ...rect, x: 2 * centerX - (rect.x + rect.w), a: -rect.a }; } // 垂直翻转函数 function flipVertically(rect) { const centerY = rect.y + rect.h / 2; return { ...rect, y: 2 * centerY - (rect.y + rect.h), a: -rect.a }; } // 原矩形 const original = { x: 30, y: 30, w: 100, h: 50, a: 0.5 }; // 水平翻转后的矩形(偏移x轴避免重叠) const flippedHoriz = flipHorizontally(original); flippedHoriz.x += 150; // 垂直翻转后的矩形(偏移y轴避免重叠) const flippedVert = flipVertically(original); flippedVert.y += 100; // 绘制原矩形(黑色) ctx.strokeStyle = "#000"; drawRotatedRectangle(ctx, original.x, original.y, original.w, original.h, original.a); // 绘制水平翻转矩形(红色) ctx.strokeStyle = "#ff0000"; drawRotatedRectangle(ctx, flippedHoriz.x, flippedHoriz.y, flippedHoriz.w, flippedHoriz.h, flippedHoriz.a); // 绘制垂直翻转矩形(蓝色) ctx.strokeStyle = "#0000ff"; drawRotatedRectangle(ctx, flippedVert.x, flippedVert.y, flippedVert.w, flippedVert.h, flippedVert.a);
<canvas></canvas>
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

