.NET GDI+如何围绕固定点旋转图形并保持指定位置
解决方案:矢量级实现旋转后图形锚点对齐需求
要实现旋转后图形的指定视觉位置对齐(比如旋转后最左侧角落在输入X坐标),无需依赖位图,直接通过Graphics的变换矩阵即可完成,核心是计算旋转后的边界偏移,调整变换顺序抵消旋转带来的位置偏移。
核心思路
直接使用RotateTransform会绕当前原点旋转,导致图形偏移。我们需要:
- 计算原始图形旋转后,其边界框相对于原始左上角的偏移量(即旋转后图形最左/最上点与原始左上角的坐标差)。
- 通过逆序变换(GDI+变换矩阵从右往左应用),先抵消偏移,再旋转,最后平移到目标位置,确保旋转后的图形锚点精准落在指定坐标。
完整代码实现
// 保存当前Graphics状态,避免影响后续绘制 var gState = e.Graphics.Save(); try { // 目标位置:旋转后图形最左侧角的X/Y坐标 float targetX = 100f; float targetY = 140f; // 原始图形尺寸 float w = 100f; float h = 20f; // 旋转角度 float rotateDeg = 45f; float rad = rotateDeg * (float)(Math.PI / 180); float cos = (float)Math.Cos(rad); float sin = (float)Math.Sin(rad); // 计算旋转后矩形四个顶点的X坐标,找到最小值(最左点的相对X) float x1 = 0; float x2 = w * cos; float x3 = w * cos - h * sin; float x4 = -h * sin; float minRelativeX = Math.Min(Math.Min(x1, x2), Math.Min(x3, x4)); // 计算旋转后矩形四个顶点的Y坐标,找到最小值(最上点的相对Y) float y1 = 0; float y2 = w * sin; float y3 = w * sin + h * cos; float y4 = h * cos; float minRelativeY = Math.Min(Math.Min(y1, y2), Math.Min(y3, y4)); // 偏移量:抵消旋转带来的左/上偏移,让旋转后图形的边界框左上角对齐原始原点 float offsetX = -minRelativeX; float offsetY = -minRelativeY; // 变换顺序:GDI+变换从右往左应用,所以调用顺序为:平移到目标→旋转→抵消偏移 e.Graphics.TranslateTransform(targetX, targetY); e.Graphics.RotateTransform(rotateDeg); e.Graphics.TranslateTransform(offsetX, offsetY, MatrixOrder.Append); // 绘制原始图形(以(0,0)为左上角) e.Graphics.DrawRectangle(Pens.Fuchsia, 0, 0, w, h); } finally { // 恢复Graphics状态 e.Graphics.Restore(gState); }
代码说明
- 顶点坐标计算:通过旋转矩阵计算原始矩形四个顶点旋转后的坐标,找到其中最左(
minRelativeX)和最上(minRelativeY)的相对坐标值。 - 偏移量计算:
offsetX = -minRelativeX确保旋转后图形的最左点对齐到原始原点的X轴,offsetY同理对齐Y轴。 - 变换顺序:GDI+的变换矩阵是右乘顺序,因此先调用
TranslateTransform(targetX, targetY),再旋转,最后追加偏移平移,最终实现旋转后的图形边界框左上角精准落在(targetX, targetY)。
该方案为纯矢量绘制,无位图的性能损耗,适用于PDF等需要矢量缩放的场景,文本显示无失真。
内容的提问来源于stack exchange,提问作者kes
相关产品推荐
相关产品推荐

