我希望允许用户使用在iOS 11 PDFKit文档中查看的PDFView。绘图应该最终嵌入到PDF中。
后一种方法是将“PDFAnnotation”类型的“墨水”添加到PDFPage中,并使用与用户绘图相对应的UIBezierPath进行解决。
但是,我如何实际记录用户在PDFView之上创建这样一个UIBezierPath的操作呢?
我尝试过在PDFView和PDFPage上重写PDFView,但它从未被调用。我尝试过添加一个UIGestureRecognizer,但什么也没有完成。
我假设以后需要使用PDFView实例方法PDFPage(_ point: CGPoint,to page: PDFPage)将获得的坐标转换为适合注释的PDF坐标。
发布于 2018-01-24 21:56:43
最后,我通过创建一个扩展PDFViewController和UIGestureRecognizerDelegate的UIViewController类来解决这个问题。我添加了一个PDFView作为子视图,向navigationItem添加了一个UIBarButtonItem,用于切换注释模式。
我在一个名为UIBezierPath的signingPath中记录这些触摸,并使用以下代码在currentAnnotation中使用PDFAnnotation类型的当前注释:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: pdfView)
signingPath = UIBezierPath()
signingPath.move(to: pdfView.convert(position, to: pdfView.page(for: position, nearest: true)!))
annotationAdded = false
UIGraphicsBeginImageContext(CGSize(width: 800, height: 600))
lastPoint = pdfView.convert(position, to: pdfView.page(for: position, nearest: true)!)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: pdfView)
let convertedPoint = pdfView.convert(position, to: pdfView.page(for: position, nearest: true)!)
let page = pdfView.page(for: position, nearest: true)!
signingPath.addLine(to: convertedPoint)
let rect = signingPath.bounds
if( annotationAdded ) {
pdfView.document?.page(at: 0)?.removeAnnotation(currentAnnotation)
currentAnnotation = PDFAnnotation(bounds: rect, forType: .ink, withProperties: nil)
var signingPathCentered = UIBezierPath()
signingPathCentered.cgPath = signingPath.cgPath
signingPathCentered.moveCenter(to: rect.center)
currentAnnotation.add(signingPathCentered)
pdfView.document?.page(at: 0)?.addAnnotation(currentAnnotation)
} else {
lastPoint = pdfView.convert(position, to: pdfView.page(for: position, nearest: true)!)
annotationAdded = true
currentAnnotation = PDFAnnotation(bounds: rect, forType: .ink, withProperties: nil)
currentAnnotation.add(signingPath)
pdfView.document?.page(at: 0)?.addAnnotation(currentAnnotation)
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: pdfView)
signingPath.addLine(to: pdfView.convert(position, to: pdfView.page(for: position, nearest: true)!))
pdfView.document?.page(at: 0)?.removeAnnotation(currentAnnotation)
let rect = signingPath.bounds
let annotation = PDFAnnotation(bounds: rect, forType: .ink, withProperties: nil)
annotation.color = UIColor(hex: 0x284283)
signingPath.moveCenter(to: rect.center)
annotation.add(signingPath)
pdfView.document?.page(at: 0)?.addAnnotation(annotation)
}
}注释切换按钮刚刚运行:
pdfView.isUserInteractionEnabled = !pdfView.isUserInteractionEnabled这确实是它的关键,因为这禁用了PDF上的滚动,并使我能够接收触摸事件。
触摸事件的记录和转换为PDFAnnotation的方式立即意味着注释在写入PDF时是可见的,并且它最终被记录到PDF中的正确位置--不管滚动位置如何。
确保它在正确的页面上结束只是一个类似的问题,就是将硬编码的0页号更改为pdfView.page( for : position,就近:true)值。
发布于 2018-01-24 21:21:49
为此,我创建了一个新的视图类(如注释视图),并在用户进行注释时将其放在PDFView的顶部。
该视图使用它的默认touchesBegan/touchesMoved/touchesEnded方法来创建一个跟随该手势的bezier路径。一旦触摸结束,我的视图就会将其保存为pdf上的注释。
注意:用户需要一种方式来决定他们是否处于注释状态。
用于我的主类
class MyViewController : UIViewController, PDFViewDelegate, VCDelegate {
var pdfView: PDFView?
var touchView: AnnotateView?
override func loadView() {
touchView = AnnotateView(frame: CGRect(x: 0, y: 0, width: 375, height: 600))
touchView?.backgroundColor = .clear
touchView?.delegate = self
view.addSubview(touchView!)
}
func addAnnotation(_ annotation: PDFAnnotation) {
print("Anotation added")
pdfView?.document?.page(at: 0)?.addAnnotation(annotation)
}
}我的注释视图
class AnnotateView: UIView {
var path: UIBezierPath?
var delegate: VCDelegate?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Initialize a new path for the user gesture
path = UIBezierPath()
path?.lineWidth = 4.0
var touch: UITouch = touches.first!
path?.move(to: touch.location(in: self))
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Add new points to the path
let touch: UITouch = touches.first!
path?.addLine(to: touch.location(in: self))
self.setNeedsDisplay()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
path?.addLine(to: touch!.location(in: self))
self.setNeedsDisplay()
let annotation = PDFAnnotation(bounds: self.bounds, forType: .ink, withProperties: nil)
annotation.add(self.path!)
delegate?.addAnnotation(annotation)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchesEnded(touches, with: event)
}
override func draw(_ rect: CGRect) {
// Draw the path
path?.stroke()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.isMultipleTouchEnabled = false
}
}发布于 2018-09-06 22:17:58
编辑:
jksoegaard的回答虽然鼓舞了我在这方面的所有工作,但也存在一个缺陷:在touchedMoved期间,创建了多个PDF注释,从而使PDF页面陷入批注的泥潭,这严重影响了它的加载时间。我编写了在CAShapeLayer阶段使用touchedMoved的代码,并且只在touchesEnded阶段创建完整的touchesEnded注释。
我的实现是UIGestureRecognizer的一个子类,它允许您在笔、荧光笔和橡皮擦之间进行选择,并选择颜色和宽度。它还包括一个撤消管理器。示例项目是这里。
原始答案
除了jksoegaard的出色回答外,我还为我这样的新手做了一些澄清:
和
let page = pdfView.page(for: position, nearest: true)!每次在您看到annotation.add或currentAnnotation.add之前,您都需要(根据该函数的需要使用注释或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)记录每一次触摸的rect都需要适应较厚的线条。而不是
let rect = signingPath.bounds试试看,10 of厚的例子如下:
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)https://stackoverflow.com/questions/47135766
复制相似问题