Как я могу повторить анимацию (используя UIViewPropertyAnimator) определенное количество раз?
Я хочу добиться эффекта пульсации для кнопки и, следовательно, нужно несколько раз повторять эффект spring, проблема в том, что я не могу найти никакой информации о том, какие параметры предоставить и как это сделать
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))
Ответы
Ответ 1
iOS 10 вводит новый объект, называемый UIViewPropertyAnimator
.
Вы можете сделать то же самое, что и с UIView.animation
, но для достижения более сложных анимаций apple предоставляет нам CoreAnimation
framework.
Почему мы должны использовать его?
Потому что UIViewPropertyAnimator
- хорошо написанный и высоко расширяемый API. Он охватывает те же функции, что и анимация в стиле UIView
, но дает вам тонкий программный контроль над анимацией. Это означает, что вы можете приостановить анимацию в процессе выполнения, перезапустить ее позже, если хотите, и даже динамически модифицировать анимационные свойства (например, изменить конечную точку анимации в верхнем правом углу экрана, когда она была ранее - оставил).
Мы создаем его экземпляр и создаем анимацию следующим образом:
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 })
Теперь мы можем взаимодействовать с анимациями, используя:
viewFrameAnimator.startAnimation..
viewFrameAnimator.stopAnimation..
viewFrameAnimator.finishAnimation(at:..
чтобы продолжить пример выше:
viewFrameAnimator.startAnimation()
Затем, чтобы вернуться к alpha
, равному 1, если нам нужно больше параметров анимации, мы также можем запустить this UIViewPropertyAnimator
открытый класс:
let viewAlphaAnimator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1.0,
delay: 0.0,
options: [.curveLinear],
animations: { view.alpha = 1.0 })
дайте нам добавить дополнительные опции анимации. Теперь вы знаете больше, чем этот новый объект.
Как его повторить?
Итак, давайте начнем объяснять, как повторять анимацию, например, если мы хотим повторить view.alpha = 1.0
для 3 раз (вы можете увидеть маленькую вспышку для каждого повторения для вывода.), вы должны следовать:
let viewAlphaAnimator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1.0,
delay: 0.0,
options: [.curveLinear,.repeat],
animations: { UIView.setAnimationRepeatCount(3);view.alpha = 1.0 })
Надеюсь, это поможет вам.
Ответ 2
Пожалуйста, используйте
pulseEffect.addCompletion({_ in
// Repeat the logic here
})
Вы можете повторить логику анимации внутри блока 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))
}
Вы также можете добавить логику, чтобы ограничить анимацию определенным числом в блоке addCompletion
Ответ 3
Этот код работает:
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()
Ответ 4
По какой-то причине они не указали возможность указать количество повторов с помощью UIPropertyAnimator. У вас останутся следующие варианты:
- Держите счетчик и повторите анимацию в обработчике завершения
и уменьшите счетчик до тех пор, пока счетчик не достигнет 0
- Анимация с неопределенным повторением, но планирование таймера и остановка
анимация (необязательно добавьте анимацию, чтобы перейти к финальной
положение)
- Отрегулируйте параметры spring, чтобы было меньше увлажнения и
больше эластичности, и вы получите больше колебаний.
- Используйте старые методы UIView.animate вместе со старым
UIView.setAnimationRepeatCount
- Использовать CASpringAnimation, поскольку это то, что аниматор Property обертывает в любом случае, и у него есть счетчик повторений.
Ответ 5
Пожалуйста, используйте этот измененный код
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))