注释允许用户在文档的特定部分添加评论、提醒或附加信息。 这些工具可以在处理 PDF 时加强协作和交流,使用户能够对共享内容进行注释、评论并提供上下文。 Y
PDF 注释在业务工作流中有多种用途:审阅者可以在文档上标注反馈意见,团队可以在不修改原始内容的情况下对合同进行协作,质量保证团队可以标记技术文档中的问题。 无论您是在构建文档管理系统还是在增强现有的 PDF 工作流程,IronPDF 的注释功能都能与您的 C# PDF 创建和 编辑功能无缝集成。 对于需要高级安全功能以及注释功能的组织,请浏览我们全面的IronPDF安全教程。
快速入门:使用IronPDF向 PDF 添加注释
本快速指南演示了如何使用 IronPDF 在 C# 中为 PDF 文档添加文本注释。 只需几行代码,开发人员即可通过添加评论或注释来增强他们的PDF,提高文档的互动性和协作性。 首先加载您的PDF并使用AddTextAnnotation方法快速插入注释。
PDF 中的文本注释功能类似于物理文档中的便签。 这些注释以小图标的形式出现在页面上,点击后可显示注释全文。 这种非侵入式方法既能保持文档的可读性,又能提供必要的反馈机制。 在处理 HTML 到 PDF 的转换时,您可以在转换后添加注释,以标记需要复查的区域或提供额外的上下文。 该功能在与 JavaScript 渲染相结合时特别有用,可用于可能需要额外说明的动态内容。
提示: 所有页面索引均采用从零开始的索引方式。
using IronPdf;using IronPdf.Annotations;ChromePdfRenderer renderer = new ChromePdfRenderer();PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Annotation</h1>");// Create a PDF annotation object on a specified page indexTextAnnotation annotation = new TextAnnotation(0){Title = "This is the title",Contents = "This is the long 'sticky note' comment content...",X = 50,Y = 700,};// Add the annotationpdf.Annotations.Add(annotation);pdf.SaveAs("annotation.pdf");
using IronPdf;
using IronPdf.Annotations;
ChromePdfRenderer renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Annotation</h1>");
// Create a PDF annotation object on a specified page index
TextAnnotation annotation = new TextAnnotation(0)
{
Title = "This is the title",
Contents = "This is the long 'sticky note' comment content...",
X = 50,
Y = 700,
};
// Add the annotation
pdf.Annotations.Add(annotation);
pdf.SaveAs("annotation.pdf");
ImportsIronPdfImportsIronPdf.AnnotationsDim renderer As New ChromePdfRenderer()Dim pdf AsPdfDocument = renderer.RenderHtmlAsPdf("<h1>Annotation</h1>")' Create a PDF annotation object on a specified page indexDim annotation As New TextAnnotation(0) With { .Title = "This is the title", .Contents = "This is the long 'sticky note' comment content...", .X = 50, .Y = 700}' Add the annotationpdf.Annotations.Add(annotation)pdf.SaveAs("annotation.pdf")
Imports IronPdf
Imports IronPdf.Annotations
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Annotation</h1>")
' Create a PDF annotation object on a specified page index
Dim annotation As New TextAnnotation(0) With {
.Title = "This is the title",
.Contents = "This is the long 'sticky note' comment content...",
.X = 50,
.Y = 700
}
' Add the annotation
pdf.Annotations.Add(annotation)
pdf.SaveAs("annotation.pdf")
去除注释对于文件定稿至关重要。 在采纳反馈意见并进行必要修改后,您可能需要在发布最终版本前清理审阅意见。 这一过程与 IronPDF 的其他功能(如 PDF 压缩)很好地整合在一起,以创建干净、优化的文档进行分发。 对于需要存档的文件,可考虑在删除注释后转换为 IronPDF/A 格式,以确保长期保存的合规性。
如何删除单个注释?
要删除单个注释,请使用RemoveAt方法,并根据注释集合的索引提供相应的索引。
using IronPdf;PdfDocument pdf = PdfDocument.FromFile("multipleAnnotation.pdf");// Remove a single annotation with specified indexpdf.Annotations.RemoveAt(1);pdf.SaveAs("removeSingleAnnotation.pdf");
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("multipleAnnotation.pdf");
// Remove a single annotation with specified index
pdf.Annotations.RemoveAt(1);
pdf.SaveAs("removeSingleAnnotation.pdf");
ImportsIronPdfPrivate pdf AsPdfDocument = PdfDocument.FromFile("multipleAnnotation.pdf")' Remove a single annotation with specified indexpdf.Annotations.RemoveAt(1)pdf.SaveAs("removeSingleAnnotation.pdf")
Imports IronPdf
Private pdf As PdfDocument = PdfDocument.FromFile("multipleAnnotation.pdf")
' Remove a single annotation with specified index
pdf.Annotations.RemoveAt(1)
pdf.SaveAs("removeSingleAnnotation.pdf")
这种批量删除功能在准备最终发布文档或实施文档版本系统时特别有用,因为在这些情况下需要删除以前审阅周期中的注释。 考虑将其与 metadata 编辑相结合,以更新文档属性并显示审核状态。 对于需要经过净化的文档的工作流,可以探索[PDF净化](https://ironpdf.com/how to sanitize-pdf/)选项,以删除包括注释在内的所有潜在敏感信息。
using IronPdf;PdfDocument pdf = PdfDocument.FromFile("multipleAnnotation.pdf");// Remove all annotaions on a specified pagepdf.Annotations.RemoveAllAnnotationsForPage(0);// Remove all annotaions on the documentpdf.Annotations.Clear();pdf.SaveAs("removeAllAnnotation.pdf");
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("multipleAnnotation.pdf");
// Remove all annotaions on a specified page
pdf.Annotations.RemoveAllAnnotationsForPage(0);
// Remove all annotaions on the document
pdf.Annotations.Clear();
pdf.SaveAs("removeAllAnnotation.pdf");
ImportsIronPdfPrivate pdf AsPdfDocument = PdfDocument.FromFile("multipleAnnotation.pdf")' Remove all annotaions on a specified pagepdf.Annotations.RemoveAllAnnotationsForPage(0)' Remove all annotaions on the documentpdf.Annotations.Clear()pdf.SaveAs("removeAllAnnotation.pdf")
Imports IronPdf
Private pdf As PdfDocument = PdfDocument.FromFile("multipleAnnotation.pdf")
' Remove all annotaions on a specified page
pdf.Annotations.RemoveAllAnnotationsForPage(0)
' Remove all annotaions on the document
pdf.Annotations.Clear()
pdf.SaveAs("removeAllAnnotation.pdf")
位置通过X, Y, Width, 和Rectangle。 链接所在页面和其目标页面均在构造函数中使用零基索引指定。
提示: X, Y, Width, 和-1。 忘记设置它们会导致无效的注释,因此请始终分配可点击区域。
using IronPdf;using IronPdf.Annotations;// Load an existing multi-page PDFPdfDocument pdf = PdfDocument.FromFile("multipage.pdf");// Create a clickable link on page 1 (index 0) that jumps to page 6 (index 5).// Page indexes are zero-based. The default DestinationType (Page) fits the// whole destination page in the viewer when the link is clicked.LinkAnnotation link = new LinkAnnotation(pageIndex: 0, destinationPageIndex: 5){X = 72, // points from the LEFT edge of the page (72 points = 1 inch)Y = 700, // BOTTOM edge of the clickable area (PDF origin is bottom-left)Width = 200,Height = 20,Contents = "Go to Chapter 6"};// LinkAnnotation lives in the same collection as TextAnnotationpdf.Annotations.Add(link);pdf.SaveAs("internal-link.pdf");
using IronPdf;
using IronPdf.Annotations;
// Load an existing multi-page PDF
PdfDocument pdf = PdfDocument.FromFile("multipage.pdf");
// Create a clickable link on page 1 (index 0) that jumps to page 6 (index 5).
// Page indexes are zero-based. The default DestinationType (Page) fits the
// whole destination page in the viewer when the link is clicked.
LinkAnnotation link = new LinkAnnotation(pageIndex: 0, destinationPageIndex: 5)
{
X = 72, // points from the LEFT edge of the page (72 points = 1 inch)
Y = 700, // BOTTOM edge of the clickable area (PDF origin is bottom-left)
Width = 200,
Height = 20,
Contents = "Go to Chapter 6"
};
// LinkAnnotation lives in the same collection as TextAnnotation
pdf.Annotations.Add(link);
pdf.SaveAs("internal-link.pdf");
using IronPdf;using IronPdf.Annotations;using IronPdf.Bookmarks;PdfDocument pdf = PdfDocument.FromFile("multipage.pdf");// 1. Scroll to a specific vertical position on the destination page (full width shown)LinkAnnotation scrollLink = new LinkAnnotation(0, 2){X = 72, Y = 680, Width = 300, Height = 16,DestinationType = BookmarkDestinations.PageY,DestinationTop = 400 // scroll so y=400 sits at the top of the view};pdf.Annotations.Add(scrollLink);// 2. Jump to a position AND set the zoom levelLinkAnnotation zoomLink = new LinkAnnotation(0, 3, "Zoom to figure"){X = 72, Y = 650, Width = 200, Height = 16,DestinationType = BookmarkDestinations.PageZoom,DestinationLeft = 100,DestinationTop = 500,DestinationZoom = 150 // 150% zoom; use 0 to inherit the current zoom};pdf.Annotations.Add(zoomLink);// 3. Fit a specific rectangle on the destination pageLinkAnnotation rectLink = new LinkAnnotation(0, 4){X = 72, Y = 620, Width = 200, Height = 16,DestinationType = BookmarkDestinations.PageRect,DestinationLeft = 50,DestinationBottom = 100,DestinationRight = 550,DestinationTop = 700};pdf.Annotations.Add(rectLink);pdf.SaveAs("link-destinations.pdf");
using IronPdf;
using IronPdf.Annotations;
using IronPdf.Bookmarks;
PdfDocument pdf = PdfDocument.FromFile("multipage.pdf");
// 1. Scroll to a specific vertical position on the destination page (full width shown)
LinkAnnotation scrollLink = new LinkAnnotation(0, 2)
{
X = 72, Y = 680, Width = 300, Height = 16,
DestinationType = BookmarkDestinations.PageY,
DestinationTop = 400 // scroll so y=400 sits at the top of the view
};
pdf.Annotations.Add(scrollLink);
// 2. Jump to a position AND set the zoom level
LinkAnnotation zoomLink = new LinkAnnotation(0, 3, "Zoom to figure")
{
X = 72, Y = 650, Width = 200, Height = 16,
DestinationType = BookmarkDestinations.PageZoom,
DestinationLeft = 100,
DestinationTop = 500,
DestinationZoom = 150 // 150% zoom; use 0 to inherit the current zoom
};
pdf.Annotations.Add(zoomLink);
// 3. Fit a specific rectangle on the destination page
LinkAnnotation rectLink = new LinkAnnotation(0, 4)
{
X = 72, Y = 620, Width = 200, Height = 16,
DestinationType = BookmarkDestinations.PageRect,
DestinationLeft = 50,
DestinationBottom = 100,
DestinationRight = 550,
DestinationTop = 700
};
pdf.Annotations.Add(rectLink);
pdf.SaveAs("link-destinations.pdf");
using IronPdf;using IronPdf.Annotations;using IronPdf.Bookmarks;using System;using System.Collections.Generic;PdfDocument pdf = PdfDocument.FromFile("report-with-toc.pdf");// Zero-based index of the page that holds the table-of-contents textint tocPageIndex = 1;// Map each TOC entry's leading text to the page index it should jump tovar tocEntries = new Dictionary<string, int>{ { "Introduction", 2 }, { "Methodology", 4 }, { "Results", 6 }, { "Conclusion", 9 },};// Walk the text chunks on the TOC page and overlay a clickable link on each matchforeach (var chunk in pdf.Pages[tocPageIndex].TextChunks){ string text = chunk.Contents.Trim(); foreach (var entry in tocEntries) { if (!text.StartsWith(entry.Key)) continue; var box = chunk.BoundingBox; pdf.Annotations.Add(new LinkAnnotation(tocPageIndex, entry.Value) {X = (int)box.Left,Y = (int)box.Bottom, // Bottom, NOT Top (PDF origin is bottom-left)Width = (int)Math.Max(box.Width, 400),Height = (int)Math.Abs(box.Top - box.Bottom),DestinationType = BookmarkDestinations.PageY,DestinationTop = 792, // top of a US Letter pageHidden = true // invisible overlay on the existing TOC text }); break; }}pdf.SaveAs("clickable-toc.pdf");
using IronPdf;
using IronPdf.Annotations;
using IronPdf.Bookmarks;
using System;
using System.Collections.Generic;
PdfDocument pdf = PdfDocument.FromFile("report-with-toc.pdf");
// Zero-based index of the page that holds the table-of-contents text
int tocPageIndex = 1;
// Map each TOC entry's leading text to the page index it should jump to
var tocEntries = new Dictionary<string, int>
{
{ "Introduction", 2 },
{ "Methodology", 4 },
{ "Results", 6 },
{ "Conclusion", 9 },
};
// Walk the text chunks on the TOC page and overlay a clickable link on each match
foreach (var chunk in pdf.Pages[tocPageIndex].TextChunks)
{
string text = chunk.Contents.Trim();
foreach (var entry in tocEntries)
{
if (!text.StartsWith(entry.Key)) continue;
var box = chunk.BoundingBox;
pdf.Annotations.Add(new LinkAnnotation(tocPageIndex, entry.Value)
{
X = (int)box.Left,
Y = (int)box.Bottom, // Bottom, NOT Top (PDF origin is bottom-left)
Width = (int)Math.Max(box.Width, 400),
Height = (int)Math.Abs(box.Top - box.Bottom),
DestinationType = BookmarkDestinations.PageY,
DestinationTop = 792, // top of a US Letter page
Hidden = true // invisible overlay on the existing TOC text
});
break;
}
}
pdf.SaveAs("clickable-toc.pdf");
源自左下角的 PDF 坐标可能会让习惯于左上角坐标系的开发人员感到困惑。 不正确的坐标计算可能会将注释放置在意想不到的位置,从而可能遮盖重要内容或出现页面外的情况。 在与用户界面框架或用户输入系统集成时,一定要适当转换坐标。
在实现点击注释功能等功能或将用户交互的屏幕坐标转换为 PDF 坐标时,理解坐标系变得更加重要。 对于复杂的定位要求,可考虑使用 IronPDF 的视口和缩放功能,以确保注释在任何查看条件下都能正确显示。
添加多个注释时如何优化性能?
添加多个注释时,请批量操作,在保存文档之前将所有注释添加到集合中。 这种方法减少了文件 I/O 操作,显著提高了性能,尤其是在处理大型 PDF 或连续处理多个文档时。 考虑在批量操作过程中实施进度指示器,以获得更好的用户体验。
// Example of batch annotation processingvar annotations = new List<TextAnnotation>();for (int i = 0; i < 100; i++){ annotations.Add(new TextAnnotation(0) { Title = $"Note {i}", Contents = $"Content for note {i}",X = 50 + (i * 10),Y = 700 - (i * 20) });}// Add all annotations at onceforeach (var annotation in annotations){ pdf.Annotations.Add(annotation);}// Save once after all additionspdf.SaveAs("batch-annotated.pdf");
// Example of batch annotation processing
var annotations = new List<TextAnnotation>();
for (int i = 0; i < 100; i++)
{
annotations.Add(new TextAnnotation(0)
{
Title = $"Note {i}",
Contents = $"Content for note {i}",
X = 50 + (i * 10),
Y = 700 - (i * 20)
});
}
// Add all annotations at once
foreach (var annotation in annotations)
{
pdf.Annotations.Add(annotation);
}
// Save once after all additions
pdf.SaveAs("batch-annotated.pdf");
ImportsSystem.Collections.Generic' Example of batch annotation processingDim annotations As New List(OfTextAnnotation)()For i AsInteger = 0 To 99 annotations.Add(New TextAnnotation(0) With { .Title = $"Note {i}", .Contents = $"Content for note {i}", .X = 50 + (i * 10), .Y = 700 - (i * 20) })Next' Add all annotations at onceFor Each annotation In annotations pdf.Annotations.Add(annotation)Next' Save once after all additionspdf.SaveAs("batch-annotated.pdf")
Imports System.Collections.Generic
' Example of batch annotation processing
Dim annotations As New List(Of TextAnnotation)()
For i As Integer = 0 To 99
annotations.Add(New TextAnnotation(0) With {
.Title = $"Note {i}",
.Contents = $"Content for note {i}",
.X = 50 + (i * 10),
.Y = 700 - (i * 20)
})
Next
' Add all annotations at once
For Each annotation In annotations
pdf.Annotations.Add(annotation)
Next
' Save once after all additions
pdf.SaveAs("batch-annotated.pdf")
Why is it important to test PDFs with annotations across different readers?
Different PDF readers render annotations differently, affecting icon styles and popup behaviors. Testing in popular viewers like Adobe Acrobat, Chrome, and mobile readers ensures consistent appearance and functionality across platforms.
What are best practices for working with PDF annotations using IronPDF?
Best practices include understanding the coordinate system starting from the bottom-left, optimizing performance by batching annotation additions, ensuring cross-viewer compatibility, and considering security measures for annotated content.