将 UIView 动画化为 "squiggle" 到达目的地的方式,而不是直线前进
Animate UIView to "squiggle" its way to destination instead of going in straight line
我有这样的动画:
bubble.frame.origin = CGPoint(x: 75, y: -120)
UIView.animate(
withDuration: 2.5,
animations: {
self.bubble.transform = CGAffineTransform(translationX: 0, y: self.view.frame.height * -1.3)
}
)
但是,动画是直线进行的。我希望动画在到达目的地的途中来回移动一点。像一个泡沫。有什么想法吗?
如果要沿路径设置动画,可以使用 CAKeyframeAnimation
。唯一的问题是你想要什么样的 path
。衰减正弦曲线可能就足够了:
func animate() {
let box = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
box.backgroundColor = .blue
box.center = bubblePoint(1)
view.addSubview(box)
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = bubblePath().cgPath
animation.duration = 5
box.layer.add(animation, forKey: nil)
}
哪里
private func bubblePath() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: bubblePoint(0))
for value in 1...100 {
path.addLine(to: bubblePoint(CGFloat(value) / 100))
}
return path
}
/// Point on curve at moment in time.
///
/// - Parameter time: A value between 0 and 1.
/// - Returns: The corresponding `CGPoint`.
private func bubblePoint(_ time: CGFloat) -> CGPoint {
let startY = view.bounds.maxY - 100
let endY = view.bounds.minY + 100
let rangeX = min(30, view.bounds.width * 0.4)
let midX = view.bounds.midX
let y = startY + (endY - startY) * time
let x = sin(time * 4 * .pi) * rangeX * (0.1 + time * 0.9) + midX
let point = CGPoint(x: x, y: y)
return point
}
产量:
我有这样的动画:
bubble.frame.origin = CGPoint(x: 75, y: -120)
UIView.animate(
withDuration: 2.5,
animations: {
self.bubble.transform = CGAffineTransform(translationX: 0, y: self.view.frame.height * -1.3)
}
)
但是,动画是直线进行的。我希望动画在到达目的地的途中来回移动一点。像一个泡沫。有什么想法吗?
如果要沿路径设置动画,可以使用 CAKeyframeAnimation
。唯一的问题是你想要什么样的 path
。衰减正弦曲线可能就足够了:
func animate() {
let box = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
box.backgroundColor = .blue
box.center = bubblePoint(1)
view.addSubview(box)
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = bubblePath().cgPath
animation.duration = 5
box.layer.add(animation, forKey: nil)
}
哪里
private func bubblePath() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: bubblePoint(0))
for value in 1...100 {
path.addLine(to: bubblePoint(CGFloat(value) / 100))
}
return path
}
/// Point on curve at moment in time.
///
/// - Parameter time: A value between 0 and 1.
/// - Returns: The corresponding `CGPoint`.
private func bubblePoint(_ time: CGFloat) -> CGPoint {
let startY = view.bounds.maxY - 100
let endY = view.bounds.minY + 100
let rangeX = min(30, view.bounds.width * 0.4)
let midX = view.bounds.midX
let y = startY + (endY - startY) * time
let x = sin(time * 4 * .pi) * rangeX * (0.1 + time * 0.9) + midX
let point = CGPoint(x: x, y: y)
return point
}
产量: