Skip to content

Instantly share code, notes, and snippets.

@policante
Created February 20, 2019 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save policante/8fef90f9304e44a97b5df0c57f6ffa07 to your computer and use it in GitHub Desktop.
Save policante/8fef90f9304e44a97b5df0c57f6ffa07 to your computer and use it in GitHub Desktop.
Classe para desenhar linha animada entre 2 pontos
class LineDrawerView: UIView {
convenience init() {
self.init(frame: .zero)
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
func drawLayer(_ startPoint: CGPoint, endPoint: CGPoint, animated: Bool, delegate: CAAnimationDelegate? = nil){
self.layer.sublayers?.forEach({ (la) in
la.removeAllAnimations()
la.removeFromSuperlayer()
})
let path = UIBezierPath()
path.move(to: startPoint)
let centerY = ((startPoint.y + endPoint.y) / 2)
path.addCurve(to: endPoint, controlPoint1: CGPoint(x: startPoint.x, y: centerY * 1.3), controlPoint2: CGPoint(x: endPoint.x, y: centerY * 0.7))
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.strokeEnd = animated ? 0 : 1
layer.lineWidth = 3
layer.lineDashPattern = [32, 16] // first is the length of dash, second is length of the gap.
layer.strokeColor = UIColor.black.cgColor
layer.fillColor = UIColor.clear.cgColor
self.layer.addSublayer(layer)
let pathArrow = UIBezierPath()
pathArrow.addArrow(start: CGPoint(x: endPoint.x, y: centerY), end: endPoint, pointerLineLength: 30, arrowAngle: CGFloat(Double.pi / 4))
let layerArrow = CAShapeLayer()
layerArrow.path = pathArrow.cgPath
layerArrow.strokeEnd = animated ? 0 : 1
layerArrow.lineWidth = 3
layerArrow.strokeColor = UIColor.black.cgColor
layerArrow.fillColor = UIColor.clear.cgColor
self.layer.addSublayer(layerArrow)
if animated {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.toValue = 1
animation.duration = 2
animation.autoreverses = false
animation.repeatCount = 0
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
layer.add(animation, forKey: "line")
let animationArrow = CABasicAnimation(keyPath: "strokeEnd")
animationArrow.toValue = 1
animationArrow.beginTime = CACurrentMediaTime() + animation.duration + 0.1
animationArrow.duration = 0.5
animationArrow.autoreverses = false
animationArrow.repeatCount = 0
animationArrow.fillMode = .forwards
animationArrow.isRemovedOnCompletion = false
animationArrow.delegate = delegate
layerArrow.add(animationArrow, forKey: "arrow")
}
}
}
extension UIBezierPath {
func addArrow(start: CGPoint, end: CGPoint, pointerLineLength: CGFloat, arrowAngle: CGFloat) {
let startEndAngle = atan((end.y - start.y) / (end.x - start.x)) + ((end.x - start.x) < 0 ? CGFloat(Double.pi) : 0)
let arrowLine1 = CGPoint(x: end.x + pointerLineLength * cos(CGFloat(Double.pi) - startEndAngle + arrowAngle), y: end.y - pointerLineLength * sin(CGFloat(Double.pi) - startEndAngle + arrowAngle))
let arrowLine2 = CGPoint(x: end.x + pointerLineLength * cos(CGFloat(Double.pi) - startEndAngle - arrowAngle), y: end.y - pointerLineLength * sin(CGFloat(Double.pi) - startEndAngle - arrowAngle))
self.move(to: end)
self.addLine(to: arrowLine1)
self.move(to: end)
self.addLine(to: arrowLine2)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment