如何在C#中计算SVG带matrix变换的circle元素绝对坐标?
计算SVG中带matrix变换的
<g>块内元素的绝对坐标(C#实现) 没问题,这个SVG坐标转换的问题我经常碰到,咱一步步来解决它!当SVG里的<g>标签带有matrix()变换时,块内元素的cx/cy都是相对该变换后坐标系的坐标,要得到它们在SVG画布上的绝对坐标,只需要把变换矩阵的规则应用到原始坐标上就行。
先搞懂SVG的matrix变换规则
SVG的matrix(a, b, c, d, e, f)对应的坐标变换公式是:
- 绝对X坐标 =
a * 原始X + c * 原始Y + e - 绝对Y坐标 =
b * 原始X + d * 原始Y + f
简单说,a和d是缩放因子,b和c负责旋转变换,e和f是平移偏移量。
C#实现步骤
1. 解析matrix字符串
首先得从transform属性里提取出6个矩阵参数:
public struct SvgTransformMatrix { public double ScaleX { get; set; } // 对应matrix里的a public double SkewY { get; set; } // 对应matrix里的b public double SkewX { get; set; } // 对应matrix里的c public double ScaleY { get; set; } // 对应matrix里的d public double TranslateX { get; set; } // 对应matrix里的e public double TranslateY { get; set; } // 对应matrix里的f } public static SvgTransformMatrix ParseSvgMatrix(string transformAttribute) { // 提取括号内的参数部分 var paramStart = transformAttribute.IndexOf('(') + 1; var paramEnd = transformAttribute.IndexOf(')'); var paramStr = transformAttribute.Substring(paramStart, paramEnd - paramStart); // 分割参数并转换为double(兼容逗号/空格分隔) var parameters = paramStr.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) .Select(double.Parse) .ToArray(); return new SvgTransformMatrix { ScaleX = parameters[0], SkewY = parameters[1], SkewX = parameters[2], ScaleY = parameters[3], TranslateX = parameters[4], TranslateY = parameters[5] }; }
2. 计算元素的绝对坐标
有了矩阵参数,直接套用公式计算就行:
public static (double AbsoluteX, double AbsoluteY) GetAbsoluteCoordinates(SvgTransformMatrix matrix, double originalX, double originalY) { var absX = matrix.ScaleX * originalX + matrix.SkewX * originalY + matrix.TranslateX; var absY = matrix.SkewY * originalX + matrix.ScaleY * originalY + matrix.TranslateY; return (absX, absY); }
用你的示例测试一下
拿你给出的例子:
<g transform="matrix(0.22427664,0,0,0.22427664,187.92687,120.25849)"> <circle cx="-445.12903" cy="-0.40998384" r="1.9938049">...</circle> </g>
解析出的矩阵参数是:
- ScaleX=0.22427664,SkewY=0,SkewX=0,ScaleY=0.22427664,TranslateX=187.92687,TranslateY=120.25849
代入circle的原始坐标cx=-445.12903、cy=-0.40998384:
var matrix = ParseSvgMatrix("matrix(0.22427664,0,0,0.22427664,187.92687,120.25849)"); var (absX, absY) = GetAbsoluteCoordinates(matrix, -445.12903, -0.40998384); // 计算结果:absX≈88.09687,absY≈120.16649
额外注意点
如果你的SVG里有嵌套的<g>块(多个transform叠加),需要先把所有父级的变换矩阵按顺序相乘,得到最终的复合矩阵,再应用到元素坐标上。矩阵相乘的规则这里就不展开了,需要的话可以再深入说~
内容的提问来源于stack exchange,提问作者Rashid Khaziev
相关产品推荐
相关产品推荐

