本文介绍了如何在图像上使用 shapelayer 和 bezierpath 绘制平滑的徒手画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
let path = UIBezierPath()
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 3
path.move(to: startPoint)
path.addLine(to: point)
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.path = path.cgPath
tempImage.layer.addSublayer(shapeLayer)
我正在使用上面的代码.每次触摸移动时调用上面的代码.我没有得到连续绘图.只有我画的最后一部分是可见的.有什么我在这里遗漏的吗.
I am using the above code. Calling the above code each tome the touch is moved. I am not getting a continuous drawing . only the final portion of my drawing is visible.Is there anything i am missing here.
推荐答案
我使用 UIBezierPath
和 CAShapeLayer
实现了流畅的绘图.这里的方法是有一个临时的贝塞尔路径.如果您想在图像上绘图,您可以尝试这样的操作 drawingLayer.content = yourImage.cgImage
.
I achieved a smooth drawing with UIBezierPath
and CAShapeLayer
. Here the approach is having a temporary bezier path.If you want to draw on top of an image probably you can try something like this drawingLayer.content = yourImage.cgImage
.
Swift 4
class DrawingView: UIView {
private var drawingLayer: CAShapeLayer?
private var currentPath: UIBezierPath?
private var temporaryPath: UIBezierPath?
private var points = [CGPoint]()
var drawColor = UIColor.blue
var lineWidth: CGFloat = 2.0
var opacity: CGFloat = 0.8
var sublayers: [CALayer] {
return self.layer.sublayers ?? [CALayer]()
}
// MARK: Init
override public init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
self.layer.removeAllAnimations()
self.layer.masksToBounds = true // Restrict the drawing within the canvas
self.backgroundColor = UIColor.white
self.isMultipleTouchEnabled = false
}
// MARK: Drawing
override func draw(_ rect: CGRect) {
// TODO: This orveriding is still required. Need to find a way to remove this
}
override func draw(_ layer: CALayer, in ctx: CGContext) {
let drawingLayer = self.drawingLayer ?? CAShapeLayer()
drawingLayer.contentsScale = UIScreen.main.scale
drawingLayer.lineWidth = lineWidth
drawingLayer.opacity = Float(opacity)
drawingLayer.lineJoin = .round
drawingLayer.lineCap = .round
drawingLayer.fillColor = UIColor.clear.cgColor
drawingLayer.miterLimit = 0
drawingLayer.strokeColor = drawColor.cgColor
let linePath = UIBezierPath()
if let tempPath = temporaryPath, let bezierPath = currentPath {
linePath.append(tempPath)
linePath.append(bezierPath)
drawingLayer.path = linePath.cgPath
}
if self.drawingLayer == nil {
self.drawingLayer = drawingLayer
self.layer.addSublayer(drawingLayer)
}
}
// MARK: - Touches
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.preciseLocation(in: self) else {
return
}
points.removeAll()
points.append(point)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.preciseLocation(in: self) else {
return
}
points.append(point)
updatePaths()
layer.setNeedsDisplay()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// single touch support
if points.count == 1 {
currentPath = createPathStarting(at: points[0])
currentPath?.lineWidth = self.lineWidth / 2.0
currentPath?.addArc(withCenter: points[0], radius: lineWidth / 4.0, startAngle: 0, endAngle: .pi * 2.0, clockwise: true)
}
finishPath()
}
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
finishPath()
}
// MARK: - Bezier paths Management
private func updatePaths() {
// update main path
while points.count > 4 {
points[3] = CGPoint(x: (points[2].x + points[4].x)/2.0, y: (points[2].y + points[4].y)/2.0)
if currentPath == nil {
currentPath = createPathStarting(at: points[0])
}
currentPath?.addCurve(to: points[3], controlPoint1: points[1], controlPoint2: points[2])
points.removeFirst(3)
temporaryPath = nil
}
// build temporary path up to last touch point
switch points.count {
case 2:
temporaryPath = createPathStarting(at: points[0])
temporaryPath?.addLine(to: points[1])
break
case 3:
temporaryPath = createPathStarting(at: points[0])
temporaryPath?.addQuadCurve(to: points[2], controlPoint: points[1])
break
case 4:
temporaryPath = createPathStarting(at: points[0])
temporaryPath?.addCurve(to: points[3], controlPoint1: points[1], controlPoint2: points[2])
break
default:
break
}
}
private func finishPath() {
// add temp path to current path to reflect the changes in canvas
if let tempPath = temporaryPath {
currentPath?.append(tempPath)
}
currentPath = nil
}
private func createPathStarting(at point: CGPoint) -> UIBezierPath {
let localPath = UIBezierPath()
localPath.move(to: point)
return localPath
}
这篇关于如何在图像上使用 shapelayer 和 bezierpath 绘制平滑的徒手画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!