Я пытаюсь сделать UIBezierPath
, который оживляет как волна или вода. Похоже на что-то вроде этого. https://dribbble.com/shots/3994990-Waves-Loading-Animation
Я использую эту анимацию как своего рода линейный график с точками данных (0-100). Я правильно нарисовал траекторию, но у меня возникли проблемы с ее анимацией.
В настоящее время она выглядит так: https://imgur.com/a/QQX4DGo с суперскоростным / быстрым движением
let dataPoints: [Double]
var displayLink: CADisplayLink?
var startTime: CFAbsoluteTime?
let background: UIView = {
let view = UIView()
return view
}()
let shapeLayer: CAShapeLayer = {
let layer = CAShapeLayer()
return layer
}()
init(frame: CGRect, data: [Double], precip: [String]) {
self.dataPoints = data
super.init(frame: frame)
addSubview(background)
background.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
background.layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = UIColor.waterColor.cgColor
shapeLayer.fillColor = UIColor.waterColor.cgColor
startDisplayLink()
}
func wave(at elapsed: Double) -> UIBezierPath {
let maxX = bounds.width
let maxY = bounds.height
func f(_ y: Double) -> CGFloat {
let random = CGFloat.random(in: 1.0...5.0)
return CGFloat(y) + sin(CGFloat(elapsed/2) * random * .pi)
}
func z(_ x: CGFloat) -> CGFloat {
let random = CGFloat.random(in: 1.0...2.0)
let position = Int.random(in: 0...1)
if(position == 0) {
return x + random
} else {
return x - random
}
}
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: maxY))
let steps = bounds.width/CGFloat(24)
var start: CGFloat = steps
for i in 0..<24 {
let x = z(start)
let y = maxY - f(dataPoints[i]*100)
let point = CGPoint(x: x, y: y)
path.addLine(to: point)
start+=steps
}
path.close()
return path
}
func startDisplayLink() {
startTime = CFAbsoluteTimeGetCurrent()
displayLink?.invalidate()
displayLink = CADisplayLink(target: self, selector:#selector(handleDisplayLink(_:)))
displayLink?.add(to: .current, forMode: .common)
displayLink?.preferredFramesPerSecond = 11
}
func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}
@objc func handleDisplayLink(_ displayLink: CADisplayLink) {
let elapsed = CFAbsoluteTimeGetCurrent() - startTime!
shapeLayer.path = wave(at: elapsed).cgPath
}