You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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在路径文本布局中不直接生效,需手动计算偏移量:

  1. 测量文本实际宽度
  2. 用路径总长度减去文本宽度,取一半作为起始偏移
  3. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:44:56