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
创建了镜像绘图,但是有足够的其他问题(如不同的坐标原点)让我回到原始实现。