首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# GDI+ 繪製印章效果:文字沿圓弧/橢圓弧均勻排版算法詳解

     編輯:關於C#

核心問題

印章製作的關鍵在於:**如何將字符沿圓弧或橢圓弧均勻分佈**。本文以圓形印章為例,橢圓僅需在弧長計算與座標映射上擴展,核心邏輯一致。

算法四步驟

  1. 計算總長度:獲取所有字符寬度之和 + 字符間距總和。
  2. 確定起始角度:根據總弧長與圓半徑換算為起始弧度,使文字居中於弧段。
  3. 計算每字符位置與角度:累加字符寬度,換算為相對圓心的極座標角度。
  4. 逐字繪製:使用 Graphics.TranslateTransform + RotateTransform 將每字符繪製至對應切線方向。

關鍵代碼:字符度量與總長度計算

private float ComputeStringLength(string text, Graphics g, 
    float[] charWidths, float intervalWidth, CharDirection direction)
{
    // 1. 量測整體尺寸(取得初略矩形)
    var sf = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap | StringFormatFlags.LineLimit);
    SizeF size = g.MeasureString(text, _font, int.MaxValue, sf);
    RectangleF layoutRect = new RectangleF(0, 0, size.Width, size.Height);

    // 2. 精確量測每個字符獨立區域
    var ranges = new CharacterRange[text.Length];
    for (int i = 0; i < text.Length; i++)
        ranges[i] = new CharacterRange(i, 1);

    sf.FormatFlags = StringFormatFlags.NoClip;
    sf.SetMeasurableCharacterRanges(ranges);
    sf.Alignment = StringAlignment.Near;

    Region[] regions = g.MeasureCharacterRanges(text, _font, layoutRect, sf);

    // 3. 累加實際字符寬度 + 間距
    float total = 0f;
    for (int i = 0; i < regions.Length; i++)
    {
        float w = (direction == CharDirection.Center || direction == CharDirection.Outside)
            ? regions[i].GetBounds(g).Width
            : regions[i].GetBounds(g).Height;
        charWidths[i] = w;
        total += w + intervalWidth;
    }
    return total - intervalWidth; // 扣除末尾多餘間距
}

繪製邏輯核心

private void DrawTextOnArc(Graphics g, string text, float radius, float startAngle, 
    float[] charWidths, float interval, CharDirection dir)
{
    float currentAngle = startAngle;
    for (int i = 0; i < text.Length; i++)
    {
        char c = text[i];
        float charW = charWidths[i];

        // 1. 計算字符中心對應的極座標角度(弧度制)
        float halfCharAngle = (charW / 2f) / radius; // 弧長 = 半徑 × 角度
        float charCenterAngle = currentAngle + halfCharAngle;

        // 2. 計算字符中心點笛卡爾座標
        float cx = centerX + radius * (float)Math.Cos(charCenterAngle);
        float cy = centerY + radius * (float)Math.Sin(charCenterAngle);

        // 3. 設定繪圖變換:平移到字符中心 → 旋轉到切線方向 → 繪製
        g.TranslateTransform(cx, cy);
        g.RotateTransform((float)(charCenterAngle * 180 / Math.PI) + 90); // 切線方向 = 半徑方向 + 90°
        
        // 4. 繪製單字符(原點在基線左下角,需微調)
        g.DrawString(c.ToString(), _font, _brush, -charW/2, -_font.Height/2);
        
        g.ResetTransform(); // 重置變換供下一字符

        // 5. 更新下一字符起始角度
        currentAngle += (charW + interval) / radius;
    }
}

方向枚舉與擴展

enum CharDirection { Center, Outside, Inside } 
// Center: 字符基線在圓周上
// Outside: 字符向外輻射(印章外圈文字常用)
// Inside: 字符向內輻射(印章內圈文字常用)

橢圓擴展重點:將半徑 `radius` 替換為橢圓參數方程,弧長計算需用橢圓積分或拉馬努金近似公式,座標映射改為 `x = a*cos(t), y = b*sin(t)`,切線角度同理推導。

總結

掌握 MeasureCharacterRanges 精確度量、弧長-角度換算、GDI+ 座標變換三大核心,即可實現高質量印章文字排版。完整專案可封裝為 SealGenerator 元件,支援雙圈文字、五角星、圖片水印等豐富功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved