PencilKit: zoom PKCanvasView, drawing blurred (swift, iOS 15)

It seems PKCanvasView overrides the property UIScrollViewDelegate which inherits from the UIScrollView to PKCanvasViewDelegate. And does not provide access to UIScrollViewDelegate.

In order to implement zooming, so I added a PKCanvasView into my own UIScrollView. And implemented delegate method viewForZooming in which return PKCanvasView.

But all drawing in PKCanvasView was blurred when zooming or scale. How to re-render drawing after zoom to make it has reasonable stroke width and clear ?

Some related code:

let canvasView = PKCanvasView()
let scrollView = UIScrollView()

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.addSubview(scrollView)
    scrollView.addSubview(canvasView)
    scrollView.delegate = self
    scrollView.minimumZoomScale = 0.5
    scrollView.maximumZoomScale = 2.5
}

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return canvasView
}

Some solutions I had tried:

1: Reset PKCanvasView contentScaleFactor

func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
    if let canvas = view {
      let contentScale = scale * UIScreen.main.scale
      canvas.contentScaleFactor = contentScale
    }
  }

Not worked!

2: Re-render PKStroke:

func reRender(_ scale: CGFloat) {
    let newStrokeWidth = strokeWidth * scale
    var newDrawingStrokes: [PKStroke] = []
    for stroke in canvasView.drawing.strokes {
      canvasView.tool = PKInkingTool(.pen, color: .red, width: newStrokeWidth)
      var newPoints = [PKStrokePoint]()
      stroke.path.forEach { (point) in
        let newPoint = PKStrokePoint(location: point.location,
                       timeOffset: point.timeOffset,
                       size: CGSize(width: newStrokeWidth, height: newStrokeWidth),
                       opacity: CGFloat(1), force: point.force,
                       azimuth: point.azimuth, altitude: point.altitude)
        newPoints.append(newPoint)
      }
      let newPath = PKStrokePath(controlPoints: newPoints, creationDate: Date())
      let newStroke = PKStroke(ink: PKInk(.pen, color: UIColor.red), path: newPath)
      newDrawingStrokes.append(newStroke)
    }
    let newDrawing = PKDrawing(strokes: newDrawingStrokes)
    canvasView.drawing = newDrawing
  }

Not worked! Still blurred, just changed strokeWidth by multiply scale.

3: I try to reset PKDrawing or PKStroke transform by using scrollView scale. Then PKDrawing position disordered and it was still blurred.

Please help me.

Post not yet marked as solved Up vote post of M-Three Down vote post of M-Three
697 views
  • Correct some my descriptions (more detail): Correct: PKCanvasViewDelegate inherits UIScrollViewDelegate, So it can conform all UIScrollViewDelegate's methods.

    However, I need to add PKCanvasView to another view(PDFView's documentView), so that can doodle on PDFDocument. I had already achieved it. But still when zooming PDFView, my PKCanvasView that as subview of PDFView's documentView was scaled too. Then the drawing was blurred. How to fix it?

Add a Comment

Replies

I literally have the exact same issue! I'm trying to zoom in a drawing without making it pixelated, but so far I haven't come across any solutions :(