Search code examples
swiftuikituiviewpropertyanimator

Shake view with UIVIewPropertyAnimator


I am trying to code shaking function with completion handler. When I call the func I can see shake itself but its magnitude is much fewer than desired values. Please have a look at the code and help me to fix the bug.

func shake(_ completion: @escaping () -> Void) {
    let animator = UIViewPropertyAnimator(duration: 0.6, curve: .linear)
    let distances: [CGFloat] = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
    for (i, value) in distances.enumerated() {
        let delayFactor = Double(i) / Double(distances.count)
        animator.addAnimations({ [center, weak self] in
            self?.center = CGPoint(x: center.x + value, y: center.y)
        },
        delayFactor: CGFloat(delayFactor))
    }
    animator.addCompletion { _ in completion() }
    animator.startAnimation()
}

Solution

  • The animations that are added using the addAnimations method run alongside any previously configured animations (source: Apple Documentation). So in your case all your animations are trying to cancel each other out.

    If you're looking for a spring-like animation, try initializing the animator with dampingRatio:

    myView.transform = CGAffineTransform(translationX: -20, y: 0)
    let animator = UIViewPropertyAnimator(duration: 1.0, dampingRatio: 0.1) {
        self.myView.transform = .identity
    }
    animator.startAnimation()
    

    If that's not quite what you're looking for, you might want to use a keyframe animation.