CALayer上下文中的镜像和交替输出描边

问题描述:

我正在为iPad设计Apple铅笔应用程序,并且想要捕获子图层中的铅笔笔触。每次铅笔移动时,我都会为子图层添加一个笔划,然后保存图像。对于下一个笔画,我绘制保存的图像,添加下一个笔画,然后再次保存。出于某种原因,每一个其他笔画都会与前一笔画相反镜像,这样看起来虚线图像会以镜像的形式显示在画面的水平中心。我知道其他方式可以完成同样的事情,但我真的很想知道为什么会发生这种情况 - 显然有些关于使用Layers和CGContext的东西我不明白。以下是重新创建问题的最小代码集。请注意,这不是我的实际代码(我用的视图和图层等),但我砸了一切都变成一个VC可以很容易在单个视图应用程序重新创建:CALayer上下文中的镜像和交替输出描边

import UIKit 

var touch: UITouch! 
var loc: CGPoint! 
var prevLoc: CGPoint! 

var lineWidth: CGFloat = 3 
var drawColor: UIColor = UIColor.black 

var myView: UIView! 
var pLay: CALayer! 
var img: CGImage! 

class ViewController: UIViewController, CALayerDelegate { 

override func viewDidLoad() { 
    super.viewDidLoad() 
    myView = self.view! 
    pLay = CALayer() 
    pLay.frame = myView.bounds 
    pLay.bounds = pLay.frame 
    pLay.delegate = self 
    myView.layer.addSublayer(pLay) 
    pLay.setNeedsDisplay() 
} 

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
    guard let touch = touches.first else { return } 
    let start = touch.location(in: myView) 
    print("START: X: \(start.x) Y: \(start.y)") 
} 

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 
    guard let touch = touches.first else { return } 
    let end = touch.location(in: myView) 
    print("END: X: \(end.x) Y: \(end.y)") 
    pLay.setNeedsDisplay() 
} 

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
    touch = touches.first 
    prevLoc = touch.previousLocation(in: myView) 
    loc = touch.location(in: myView) 
    if ((loc.x != prevLoc.x) && (loc.y != prevLoc.y)) { 
     print("MOVED: prev: \(prevLoc.x), \(prevLoc.y) loc: \(loc.x), \(loc.y)") 
     pLay.setNeedsDisplay() 
    } 
} 

func draw(_ layer: CALayer, in con: CGContext) { 
    guard let t = touch else { 
     return 
    } 

    if (img != nil) { 
     con.draw(img, in: layer.bounds) 
    } 

    if t.type == .stylus { 
     lineWidth = 2 
     con.setStrokeColor(drawColor.cgColor) 
    } 

    con.setLineWidth(lineWidth) 
    con.setLineCap(.round) 

    con.move(to: CGPoint(x: prevLoc.x, y: prevLoc.y)) 
    con.addLine(to: CGPoint(x: loc.x, y: loc.y)) 
    con.strokePath() 
    img = con.makeImage() 
} 

}

这是“如果没有损坏就不修复”的情况。我有这个代码工作正常使用ImageView,但觉得它效率低,所以试图在图层中实现。我试图保存状态然后在图层中恢复的方式基本上是不合适的。这里主要的问题是调用con.draw(img, in: layer.bounds),而draw创建了镜像绘图,但是有足够的其他问题(如不同的坐标原点)让我回到原始实现。