平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“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。
落到代码里,总的来说,C# PDF绘制形状适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。