web-dev-qa-db-fra.com

Comment répéter une animation (en utilisant UIViewPropertyAnimator) un certain nombre de fois?

Je souhaite obtenir un effet de pulsation pour le bouton, et il est donc nécessaire de répéter l'effet de ressort plusieurs fois. Le problème est que je ne trouve aucune information sur les paramètres à fournir et sur la manière de le faire.

let btnView = sayWordBtn.viewWithTag(0)
    btnView.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
    let mass: CGFloat = 2.0 // weight of the object
        let stiffness: CGFloat = 25.0 //elasticity
        let damping: CGFloat = 2*sqrt(mass*stiffness) // point where the system comes to rest in the shortest period of time
        let underDamping: CGFloat = damping * 0.5
        let initialVelocity: CGVector = CGVector.zero
        let springParameters: UISpringTimingParameters = UISpringTimingParameters(mass: mass, stiffness: stiffness, damping: underDamping, initialVelocity: initialVelocity)
        let animationDelay = 3

        let pulseEffect = UIViewPropertyAnimator(duration: 5, timingParameters: springParameters)
        pulseEffect.addAnimations( {[weak self] in
          btnView!.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
          })
        pulseEffect.isReversed = true
        pulseEffect.startAnimation(afterDelay: TimeInterval(animationDelay))
12
spin_eight

iOS 10 introduit un nouvel objet appelé UIViewPropertyAnimator . Vous pouvez faire la même chose que vous avez fait avec UIView.animation mais pour réaliser des animations plus complexes, Apple nous fournit le cadre CoreAnimation

Pourquoi devrions-nous l'utiliser?

Parce que UIViewPropertyAnimator est une API bien écrite et hautement extensible. Il couvre une grande partie des mêmes fonctionnalités que les animations "à l'ancienne" UIView, mais vous offre un contrôle programmatique fin de l'animation. Cela signifie que vous pouvez mettre en pause une animation en cours, la redémarrer à une date ultérieure si vous le souhaitez et même modifier dynamiquement les propriétés pouvant être animées (par exemple, le point de fin de l'animation en haut à droite de l'écran alors à gauche. Nous en créons une instance et une animation comme suit:

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.alpha = 0.35 
view.backgroundColor = .red
self.view.addSubview(view)
let newFrame = CGRect(x: 0, y: 0, width: 50, height: 50)
let viewFrameAnimator = UIViewPropertyAnimator(duration: 1.0, 
                                                  curve: .linear, 
                                             animations: { view.frame = newFrame })

Nous pouvons maintenant interagir avec les animations en utilisant:

viewFrameAnimator.startAnimation..
viewFrameAnimator.stopAnimation..
viewFrameAnimator.finishAnimation(at:..

pour continuer l'exemple ci-dessus:

viewFrameAnimator.startAnimation()

Ensuite, pour revenir à alpha égal à 1 , si nous avons besoin de plus d’options d’animations, nous pouvons également lancer thisUIViewPropertyAnimator open class:

let viewAlphaAnimator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1.0, 
                                                       delay: 0.0,
                                                     options: [.curveLinear],
                                                  animations: { view.alpha = 1.0 })

laissez-nous vous donner plus d'options d'animation. Maintenant, vous en savez plus que ce nouvel objet. 

Comment le répéter?

Commençons donc à expliquer comment répéter l'animation, par exemple si nous voulons répéter le view.alpha = 1.0 pour 3 times (vous pouvez voir la petite lumière clignotante pour chaque répétition à afficher ..), vous devez suivre:

let viewAlphaAnimator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1.0,
                                                delay: 0.0,
                                                options: [.curveLinear,.repeat],
                                                animations: { UIView.setAnimationRepeatCount(3);view.alpha = 1.0 })

J'espère que cela pourra vous aider.

10
Alessandro Ornano

Veuillez utiliser 

    pulseEffect.addCompletion({_ in
            // Repeat the logic here
    })

Vous pouvez répéter la logique d'animation à l'intérieur du bloc addCompletion

func animateView() {
    btnView.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
    let mass: CGFloat = 2.0 // weight of the object
    let stiffness: CGFloat = 25.0 // elasticity
    let damping: CGFloat = 2*sqrt(mass*stiffness) // point where the system comes to rest in the shortest period of time
    let underDamping: CGFloat = damping * 0.5
    let initialVelocity: CGVector = CGVector.zero
    let springParameters: UISpringTimingParameters = UISpringTimingParameters(mass: mass, stiffness: stiffness, damping: underDamping, initialVelocity: initialVelocity)
    let animationDelay = 3

    let pulseEffect = UIViewPropertyAnimator(duration: 5, timingParameters: springParameters)
    pulseEffect.addAnimations( {[weak self] in
        self?.btnView!.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
        })
    pulseEffect.addCompletion({_ in
        self.animateView()
    })
    pulseEffect.isReversed = true
    pulseEffect.startAnimation(afterDelay: TimeInterval(animationDelay))
}

Vous pouvez également ajouter la logique pour restreindre l'animation à un nombre spécifique dans le bloc addCompletion.

2
Lineesh K Mohan

Pour une raison quelconque, ils ont laissé la possibilité de spécifier un nombre de répétitions avec UIPropertyAnimator. Il vous reste les options suivantes:

  1. Gardez un compteur et répétez l'animation dans le gestionnaire d'achèvement Et décrémentez le compteur jusqu'à ce que le compteur atteigne 0
  2. Animer avec une répétition indéfinie mais programmer un minuteur et arrêter l'animation (Ajouter éventuellement une animation pour passer à la position finale )
  3. Ajustez les paramètres de votre ressort pour qu’il y ait moins d’amortissement et Plus d’élasticité et que vous obteniez plus d’oscillations.
  4. Utilisez les anciennes méthodes UIView.animate avec l’ancien UIView.setAnimationRepeatCount
  5. Utilisez CASpringAnimation puisque c’est de toute façon ce que l’animateur de propriétés encapsule et il compte un nombre de répétitions.
2
Josh Homann

Ce code fonctionne:

func usePropertyAnimator(_ reversed: Bool = false) {

    let circleAnimator = UIViewPropertyAnimator(
        duration: 2, timingParameters: UICubicTimingParameters())

    circleAnimator.addAnimations {
        circle.center.y += (reversed ? -1 : 1) * 330
    }

    circleAnimator.addCompletion { _ in
        usePropertyAnimator(!reversed)
    }

    circleAnimator.startAnimation()

}

usePropertyAnimator()
0
Rain

Veuillez utiliser ce code modifié 

let btnView = sayWordBtn.viewWithTag(0)
btnView.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
let mass: CGFloat = 2.0 // weight of the object
let stiffness: CGFloat = 25.0 //elasticity
let damping: CGFloat = 2*sqrt(mass*stiffness) // point where the system comes to rest in the shortest period of time
let underDamping: CGFloat = damping * 0.5
let initialVelocity: CGVector = CGVector.zero
let springParameters: UISpringTimingParameters = UISpringTimingParameters(mass: mass, stiffness: stiffness, damping: underDamping, initialVelocity: initialVelocity)
let animationDelay = 3

let pulseEffect = UIViewPropertyAnimator(duration: 5, timingParameters: springParameters)
pulseEffect.addAnimations( {[weak self] in
    UIView.setAnimationRepeatCount(3)
    UIView.setAnimationRepeatAutoreverses(true)
    btnView!.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
})
pulseEffect.isReversed = true
pulseEffect.startAnimation(afterDelay: TimeInterval(animationDelay))
0
Arun Ammannaya