C# 生成 PDF 图形:坐标系统与绘制技巧

在 PDF 中绘制形状是生成报表、图纸或数据可视化文档的常见需求。本文以 Free Spire.PDF for .NET 为例,介绍如何在 C# 中绘制线条、矩形、椭圆、多边形以及自定义路径,并说明坐标系统和透明度设置等关键细节。

环境准备

在 Visual Studio 中通过 NuGet 安装 Free Spire.PDF:

Install-Package FreeSpire.PDF

安装后引入命名空间:

using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;

坐标系统

Spire.PDF 的坐标系统与 Adobe PDF 规范不同:原点位于页面左上角,X 轴向右延伸,Y 轴向下延伸,单位是磅 (point)。A4 页面右下角坐标为 (595, 842)。这种设计方便自上而下布局内容。

新建页面时,默认包含 40 磅的页边距,坐标原点位于边距内侧的左上角。如果需要在边缘区域绘制图形,创建页面时将边距设为 0:

PdfDocument doc = new PdfDocument();
PdfPageBase page = doc.Pages.Add(PdfPageSize.A4, new PdfMargins(0));

画笔与画刷

Spire.PDF 用 PdfPen 描边,用 PdfBrush 填充。PdfPen 可指定颜色和线宽:

PdfPen pen = new PdfPen(Color.ForestGreen, 0.1f);
PdfPen penThick = new PdfPen(Color.Red, 3f);

填充使用 PdfSolidBrush:

PdfBrush brush = new PdfSolidBrush(Color.DeepSkyBlue);

绘制基本形状

所有绘制操作通过 PdfPageBase.Canvas 完成。在绘制前先保存图形状态,避免影响后续操作:

PdfDocument doc = new PdfDocument();
PdfPageBase page = doc.Pages.Add();
PdfGraphicsState state = page.Canvas.Save();

// 绘制矩形(描边)
page.Canvas.DrawRectangle(pen, 
    new RectangleF(new PointF(2, 22), new SizeF(120, 120)));

// 绘制扇形/圆形(360°扇形即为圆)
page.Canvas.DrawPie(penThick, 150, 30, 100, 90, 360, 360);

// 绘制椭圆(填充)
page.Canvas.DrawEllipse(brush, 350, 40, 20, 60);

page.Canvas.Restore(state);
doc.SaveToFile("Shapes.pdf");

DrawRectangle 接受 PdfPen 和 RectangleF 参数。DrawPie 的后四个参数分别是起止角度(以度为单位),360° 的扇形等价于一个完整圆形。DrawEllipse 既可用画刷填充,也可用画笔描边。

绘制线条与多边形

线条使用 DrawLine,多边形使用 DrawPolygon:

// 绘制线条
page.Canvas.DrawLine(pen, new PointF(50, 200), new PointF(300, 200));

// 绘制三角形(多边形)
PointF[] trianglePoints = {
    new PointF(100, 250),
    new PointF(200, 350),
    new PointF(0, 350)
};
page.Canvas.DrawPolygon(pen, brush, trianglePoints);

DrawPolygon 接受 PdfPen、PdfBrush 和 PointF[] 数组,传入 null 可只描边或只填充。

绘制弧形与贝塞尔曲线

弧形和贝塞尔曲线可组合出更复杂的图形:

// 绘制弧形
page.Canvas.DrawArc(pen, new RectangleF(50, 400, 100, 80), 0, 180);

// 绘制贝塞尔曲线
page.Canvas.DrawBezier(pen, 
    200, 400,   // 起点
    250, 350,   // 控制点1
    350, 450,   // 控制点2
    400, 400    // 终点
);

DrawArc 的第三、四个参数是起始角度和扫过角度。DrawBezier 需要起点、两个控制点和终点共四个坐标点。

使用 PdfPath 构建自定义路径

对于需要组合多个基本图形元素的情况,PdfPath 更灵活。它可以依次添加线段、矩形、多边形和贝塞尔曲线,最后一次性绘制:

PdfPath path = new PdfPath();
path.AddLine(50, 500, 150, 500);
path.AddRectangle(new RectangleF(180, 500, 60, 60));
path.AddPolygon(new PointF[] {
    new PointF(280, 500), new PointF(330, 560), new PointF(230, 560)
});
path.AddBezier(400, 500, 430, 480, 470, 520, 500, 500);

page.Canvas.DrawPath(pen, path);

PdfPath 的各个 Add 方法不立即绘制,而是将图形元素追加到路径中,最后通过 DrawPath 统一渲染。

设置透明度

通过 SetTransparency 控制图形的透明度,取值范围 0(全透明)到 1(不透明):

page.Canvas.Save();
page.Canvas.SetTransparency(0.5f);
PdfBrush semiBrush = new PdfSolidBrush(Color.Blue);
page.Canvas.DrawRectangle(semiBrush, new RectangleF(50, 600, 200, 80));
page.Canvas.Restore(state);

透明度设置作用于画布状态,建议配合 Save/Restore 使用,避免影响后续绘制。

图形状态管理

Save 和 Restore 成对使用,将图形状态(画笔颜色、线宽、透明度、坐标变换等)压栈和出栈:

PdfGraphicsState state = page.Canvas.Save();

// 一系列绘制操作,可能修改了画笔、透明度、坐标系

page.Canvas.Restore(state);
// 此后的绘制恢复到 Save 时的状态

如果需要在绘制图形前对坐标系做平移、旋转或缩放,也应放在 Save/Restore 之间,避免影响页面其他内容的定位。

完整示例

以下代码在单个 PDF 页面中绘制多种形状:

using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;

namespace PdfShapeDemo
{
    class Program
    {
        static void Main()
        {
            PdfDocument doc = new PdfDocument();
            PdfPageBase page = doc.Pages.Add(PdfPageSize.A4, new PdfMargins(20));

            PdfGraphicsState state = page.Canvas.Save();

            PdfPen greenPen = new PdfPen(Color.ForestGreen, 1.5f);
            PdfPen redPen = new PdfPen(Color.Red, 2f);
            PdfBrush blueBrush = new PdfSolidBrush(Color.DeepSkyBlue);
            PdfBrush orangeBrush = new PdfSolidBrush(Color.Orange);

            // 矩形
            page.Canvas.DrawRectangle(greenPen,
                new RectangleF(30, 40, 100, 60));

            // 圆形
            page.Canvas.DrawPie(redPen, 160, 40, 60, 60, 360, 360);

            // 填充椭圆
            page.Canvas.DrawEllipse(blueBrush, 250, 40, 80, 50);

            // 线条
            page.Canvas.DrawLine(greenPen,
                new PointF(30, 130), new PointF(350, 130));

            // 三角形
            page.Canvas.DrawPolygon(redPen, orangeBrush, new PointF[] {
                new PointF(30, 160),
                new PointF(90, 250),
                new PointF(-30, 250)
            });

            // 弧形
            page.Canvas.DrawArc(greenPen,
                new RectangleF(180, 160, 100, 80), 0, 180);

            // 半透明矩形
            page.Canvas.SetTransparency(0.4f);
            page.Canvas.DrawRectangle(new PdfSolidBrush(Color.Purple),
                new RectangleF(30, 300, 200, 80));

            page.Canvas.Restore(state);
            doc.SaveToFile("Output.pdf");
            doc.Close();
        }
    }
}

注意事项

绘制多边形时,PointF 坐标的顺序决定了图形的形状,应确保顶点按顺时针或逆时针排列。DrawRectangle 的 RectangleF 使用左上角坐标和尺寸,而非右下角坐标。A4 页面内容区域约为 595×842 磅,绘制超出此范围的图形不会显示在页面上。透明度的设置会持续影响画布状态,若后续绘制不需要透明效果,务必在 Restore 之后或重新设置透明度为 1。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容