如何用ImageSharp沿逆时针ArcLineSegment绘制居中对齐文本?
因ImageSharp.Drawing的GitHub讨论3周未得到回复,特此转帖
问题描述
我尝试复刻如下效果:
![在下方圆弧绘制圆形和文本]
使用了以下代码:
public void Draw(string text) { var imageSize = 300; var fontSize = 18; var border = 10; var color = Color.ParseHex("#808080"); FontFamily family = SystemFonts.Get("Arial"); Font font = new(family, fontSize); var radius = imageSize / 2; var center = new PointF(radius, radius); var img = Image<Rgba32>.Load(@"C:\Users\sergi\Downloads\comet.png"); img.Mutate(o => o.Resize(new Size(imageSize, imageSize))); var topSegment = new ArcLineSegment(center, new SizeF(radius-border, radius-border), 0, -220, 260); PathBuilder pathBuilder = new PathBuilder(); pathBuilder.AddSegment(topSegment); var textSegment = new ArcLineSegment(center, new SizeF(radius- fontSize/2 - border, radius- fontSize/2-border), 0, -220, -100); IPath textShape = new Polygon(textSegment); TextOptions textOptions = new(font) { WrappingLength = textShape.ComputeLength(), VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, TextAlignment = TextAlignment.Center, TextDirection = TextDirection.LeftToRight }; DrawingOptions options = new() { GraphicsOptions = new() { ColorBlendingMode = PixelColorBlendingMode.Multiply } }; IPen pen = Pens.Solid(color, 1); img.Mutate(x => x.Draw(color, 2, pathBuilder.Build())); img.Mutate(x => x.Draw(color, 2, new PathBuilder().AddSegment(textSegment).Build())); IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, textShape, textOptions); img.Mutate(i => i.Fill(color, glyphs)); string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine( "test.png"))); IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath)); img.Save(fullPath); Console.WriteLine($"Saved to {fullPath}"); }
但得到的结果是:
![结果图]
我该如何让文本占满圆弧空间,使居中对齐真正将文本置于圆弧中心?
我测试了更简单的线段也遇到同样问题:
![线段示例图]
var textSegment = new LinearLineSegment(new PointF(50, 150), new PointF(250, 150)); IPath textShape = new Polygon(textSegment); TextOptions textOptions = new(font) { //WrappingLength = textShape.ComputeLength(), VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Center, TextAlignment = TextAlignment.Center, };
同样地,TextAlignment无效果,设置HorizontalAlignment.Center会使文本对齐到线段起点的中部;另外textShape.ComputeLength()返回值为400,但实际线段仅200长,这也很奇怪。
恳请各位帮忙解答,谢谢!
解决方案
1. 修复路径长度计算异常
用Polygon包裹线段会自动闭合路径(连接起点和终点),导致计算的长度是原线段的2倍。直接将线段本身作为IPath使用即可:
// 替换原textShape定义,去掉Polygon包装 IPath textShape = textSegment;
2. 实现文本沿路径居中
TextAlignment.Center在路径文本布局中不直接生效,需手动计算偏移量:
- 测量文本实际宽度
- 用路径总长度减去文本宽度,取一半作为起始偏移
- 通过
TextOptions.Offset设置偏移实现居中
修改后的文本处理代码:
IPath textShape = textSegment; float pathLength = textShape.ComputeLength(); // 测量文本宽度 SizeF textSize = TextMeasurer.Measure(text, new TextOptions(font)); float textWidth = textSize.Width; // 计算居中偏移 float offsetX = (pathLength - textWidth) / 2; TextOptions textOptions = new(font) { WrappingLength = pathLength, TextAlignment = TextAlignment.Left, Offset = new PointF(offsetX, 0), TextDirection = TextDirection.LeftToRight }; IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, textShape, textOptions); img.Mutate(i => i.Fill(color, glyphs));
3. 微调圆弧文本位置
若文本与圆弧贴合度不佳,可调整ArcLineSegment的半径值,或通过TextOptions.Offset的Y值进行垂直方向的微调,确保文本对齐圆弧。
内容的提问来源于stack exchange,提问作者Wizche
相关产品推荐
相关产品推荐

