OK, I am new to UIBezierPaths but I need to have a path whose endpoint updates according to where the user's finger is. It should change in touchesMoved
So far I have:
func customInit() {
print("init scene")
self.backgroundColor = UIColor.cyan
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 300, y: 300))
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 3.0
self.layer.addSublayer(shapeLayer)
}
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
var touch : UITouch! = touches.first! as UITouch
var location = touch.location(in: self)
path.move(to: location)
}
I thought this would update the path endpoint but nothing happens beyond drawing the original line. I would like to not use SKScene for this, but don't know what is going wrong.
How can I make a line always have a point at the point of user's tap?
You're very close! You're missing just a few things.
When touchesMoved
is called, you need to update the path and re-assign it to the CAShapeLayer
so that it can be re-drawn. Right now you are just making a modification to the path object, but not re-drawing it.
Final Code
class DrawingView: UIView {
let startingPoint = CGPoint(x: 0, y: 0)
let shapeLayer = CAShapeLayer()
let path = UIBezierPath()
override init(frame: CGRect) {
super.init(frame: frame)
customInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
customInit()
}
func customInit() {
backgroundColor = UIColor.cyan
path.move(to: startingPoint)
path.addLine(to: CGPoint(x: 50, y: 50))
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 3.0
layer.addSublayer(shapeLayer)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
let touch = touches.first as! UITouch
let location = touch.location(in: self)
path.removeAllPoints()
path.move(to: startingPoint)
path.addLine(to: location)
shapeLayer.path = path.cgPath
}
}
Final Result
(tested in an Xcode 8.3.2 playground)
Update:
To make the line disappear when the touch is released, use touchesEnded
. Inside this method, simply remove the points on the path and reassign it to the shapeLayer so the view is updated.
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
path.removeAllPoints()
shapeLayer.path = path.cgPath
}