编辑:
jksoegaard 的回答虽然是我在这个问题上所有工作的灵感来源,但有一个缺陷:在 touchMoved 期间,会创建多个 PDF 注释,因此 PDF 页面会陷入注释,从而严重影响其加载时间。我编写的代码在touchesMoved 阶段绘制了一个CAShapeLayer,并且只在touchesEnded 阶段创建了完整的PDF 注释。
我的实现是 UIGestureRecognizer 的子类,它允许您在笔、荧光笔和橡皮擦之间进行选择,并选择颜色和宽度。它还包括一个撤消管理器。示例项目是here。
原答案
除了 jksoegaard 的出色回答之外,还有一些对像我这样的新手的澄清:
-
您需要在项目中包含 UIBezierPath+.swift 才能识别 .moveCenter 和 rect.center。从https://github.com/xhamr/paintcode-path-scale下载。
-
这些行可以被排除:
UIGraphicsBeginImageContext(CGSize(width: 800, height: 600))
和
let page = pdfView.page(for: position, nearest: true)!
-
你需要在函数之外声明一些全局变量:
var signingPath = UIBezierPath()
var annotationAdded : Bool?
var lastPoint : CGPoint?
var currentAnnotation : PDFAnnotation?
-
最后,如果你想让墨水更宽、颜色更漂亮,你需要做两件事:
一个。每次在看到 annotation.add 或 currentAnnotation.add 之前,您都需要(根据该函数的需要使用 annotation 或 currentAnnotation):
let b = PDFBorder()
b.lineWidth = { choose a pixel number here }
currentAnnotation?.border = b
currentAnnotation?.color=UIColor.{ your color of choosing }
我建议为颜色指定低 alpha。结果很漂亮,并且受您的划水速度的影响。例如,红色将是:
UIColor(red: 255/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.1)
b.记录每次触摸的矩形需要适应较粗的线条。而不是
let rect = signingPath.bounds
试一试,以 10px 的厚度为例:
let rect = CGRect(x:signingPath.bounds.minX-5,
y:signingPath.bounds.minY-5, width:signingPath.bounds.maxX-
signingPath.bounds.minX+10, height:signingPath.bounds.maxY-
signingPath.bounds.minY+10)
重要提示:touchesEnded 函数也使用了 currentAnnotation 变量。您还必须在该函数中重复 rect 的定义(无论是简短的还是我上面建议的),并在那里重复 currentAnnotation 的定义:
currentAnnotation = PDFAnnotation(bounds: rect, forType: .ink, withProperties: nil)
如果你不这样做,一个没有移动的点击会导致你的应用崩溃。
我可以验证,一旦文件被保存,注释就会被保留。保存示例代码:
let pdfData = pdfDocument?.dataRepresentation()
let annotatedPdfUrl = URL(fileURLWithPath: "\
(NSSearchPathForDirectoriesInDomains(.documentsDirectory, .userDomainMask,
true)[0])/AnnotatedPDF.pdf")
try! pdfData!.write(to: annotatedPdfUrl)