Apple 的 PDFKit:使用 Ink 注释免费绘图
Apple's PDFKit: Free draw with Ink annotation
我只想使用 PDFKit 在 PDF 文件上绘图。这听起来很简单,但我遇到了很多麻烦。从文档来看,墨水注释似乎适用于此。这是我的代码:
/// Adds a new annotation
func addAnnotation(color: UIColor, point: CGPoint) {
currentPage = pdfView.page(for: point, nearest: false)
// Here I convert the coordinates to the document and create a new annotation
if currentPage != nil {
let topRight = pdfView.convert(pdfView.frame.topRightCorner, to: currentPage!)
newAnnotation = PDFAnnotation(bounds: CGRect(origin: .zero, size: CGSize(width: topRight.x, height: topRight.y)), forType: .ink, withProperties: nil)
newAnnotation!.color = color
currentPage!.addAnnotation(newAnnotation!)
}
else {
newAnnotation = PDFAnnotation()
}
}
/// Adds a new path, maybe a new annotation
func addPath(color: UIColor, point: CGPoint, lineWidth: CGFloat) {
// Create annotation
if newAnnotation == nil {
addAnnotation(color: color, point: point)
}
guard currentPage != nil else { return }
let convertedPoint = pdfView.convert(point, to: currentPage!)
// Create initial path
let path = UIBezierPath()
path.lineWidth = 200
path.move(to: convertedPoint)
path.addLine(to: convertedPoint)
newAnnotation!.add(path)
}
/// Updates the last drawn annotation
func updatePath(point: CGPoint) {
if let annotation = newAnnotation, let page = currentPage {
let convertedPoint = pdfView.convert(point, to: page)
let lastPath = annotation.paths!.last!
lastPath.addLine(to: convertedPoint)
annotation.remove(lastPath)
annotation.add(lastPath)
}
}
我的主要问题是性能。我写了所有这些代码只是为了有一个功能性的绘图程序。过程中我的理解:
- 将注释中的路径分组而不是每个路径一个注释似乎更有效。所以我添加了 addAnnotation() 方法,它有时会创建一个新的注释。
- 创建注释时的 'bounds' 属性 对性能有很大影响。将此 属性 设置为页面的边界使程序非常 slow.But 问题是,在用户完成绘制之前我不知道注释的边界...
我有一个方法 touchMoved(),我想在路径中添加一个点。一开始,我只是在做:
if let annotation = newAnnotation, let page = currentPage {
let convertedPoint = pdfView.convert(point, to: page)
let lastPath = annotation.paths!.last!
lastPath.addLine(to: convertedPoint)
}
但是路径没有更新,所以我添加了以下行:
annotation.remove(lastPath)
annotation.add(lastPath)
事实证明,这在性能方面确实很糟糕(路径有时会消失,然后又会重新出现)。
我假设有更好的方法来完成所有这些,但我找不到任何好的例子。如果您有 PDFKit 上的 Ink 注释的工作示例,那也很好。
附带问题:在我的代码中,我将bezierPath 的lineWidth 设置为200。这是因为我想更改注释的lineWidth,但是更改bezierPath 的lineWidth 似乎并没有改变任何东西。对此有什么想法吗?
我的观察与你的相似。我发现操作 PDFAnnotation 很麻烦,主要是因为一个错误 (PDFAnnotation with PDFAnnotationSubtype equal to .widget is not refreshing its appearance after adding it to PDFPage)。
将它们删除并读取到 PDFView
的技巧是一个令人讨厌的解决方法。
也许尝试不同的方法会更好?
例如:
- 使用
CoreGraphics
在 PDFView 顶部绘制(透明)CGLayer
。
- 将绘图图层转换为
UIImage
。
- 为您的
PDFView
添加带有图像的注释。您可以查看 Apple 示例以了解如何操作。 https://developer.apple.com/library/content/samplecode/PDFAnnotationEditor/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004035
我只想使用 PDFKit 在 PDF 文件上绘图。这听起来很简单,但我遇到了很多麻烦。从文档来看,墨水注释似乎适用于此。这是我的代码:
/// Adds a new annotation
func addAnnotation(color: UIColor, point: CGPoint) {
currentPage = pdfView.page(for: point, nearest: false)
// Here I convert the coordinates to the document and create a new annotation
if currentPage != nil {
let topRight = pdfView.convert(pdfView.frame.topRightCorner, to: currentPage!)
newAnnotation = PDFAnnotation(bounds: CGRect(origin: .zero, size: CGSize(width: topRight.x, height: topRight.y)), forType: .ink, withProperties: nil)
newAnnotation!.color = color
currentPage!.addAnnotation(newAnnotation!)
}
else {
newAnnotation = PDFAnnotation()
}
}
/// Adds a new path, maybe a new annotation
func addPath(color: UIColor, point: CGPoint, lineWidth: CGFloat) {
// Create annotation
if newAnnotation == nil {
addAnnotation(color: color, point: point)
}
guard currentPage != nil else { return }
let convertedPoint = pdfView.convert(point, to: currentPage!)
// Create initial path
let path = UIBezierPath()
path.lineWidth = 200
path.move(to: convertedPoint)
path.addLine(to: convertedPoint)
newAnnotation!.add(path)
}
/// Updates the last drawn annotation
func updatePath(point: CGPoint) {
if let annotation = newAnnotation, let page = currentPage {
let convertedPoint = pdfView.convert(point, to: page)
let lastPath = annotation.paths!.last!
lastPath.addLine(to: convertedPoint)
annotation.remove(lastPath)
annotation.add(lastPath)
}
}
我的主要问题是性能。我写了所有这些代码只是为了有一个功能性的绘图程序。过程中我的理解:
- 将注释中的路径分组而不是每个路径一个注释似乎更有效。所以我添加了 addAnnotation() 方法,它有时会创建一个新的注释。
- 创建注释时的 'bounds' 属性 对性能有很大影响。将此 属性 设置为页面的边界使程序非常 slow.But 问题是,在用户完成绘制之前我不知道注释的边界...
我有一个方法 touchMoved(),我想在路径中添加一个点。一开始,我只是在做:
if let annotation = newAnnotation, let page = currentPage { let convertedPoint = pdfView.convert(point, to: page) let lastPath = annotation.paths!.last! lastPath.addLine(to: convertedPoint) }
但是路径没有更新,所以我添加了以下行:
annotation.remove(lastPath)
annotation.add(lastPath)
事实证明,这在性能方面确实很糟糕(路径有时会消失,然后又会重新出现)。
我假设有更好的方法来完成所有这些,但我找不到任何好的例子。如果您有 PDFKit 上的 Ink 注释的工作示例,那也很好。
附带问题:在我的代码中,我将bezierPath 的lineWidth 设置为200。这是因为我想更改注释的lineWidth,但是更改bezierPath 的lineWidth 似乎并没有改变任何东西。对此有什么想法吗?
我的观察与你的相似。我发现操作 PDFAnnotation 很麻烦,主要是因为一个错误 (PDFAnnotation with PDFAnnotationSubtype equal to .widget is not refreshing its appearance after adding it to PDFPage)。
将它们删除并读取到 PDFView
的技巧是一个令人讨厌的解决方法。
也许尝试不同的方法会更好? 例如:
- 使用
CoreGraphics
在 PDFView 顶部绘制(透明)CGLayer
。 - 将绘图图层转换为
UIImage
。 - 为您的
PDFView
添加带有图像的注释。您可以查看 Apple 示例以了解如何操作。 https://developer.apple.com/library/content/samplecode/PDFAnnotationEditor/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004035