Как настроить анимационную кривую при использовании анимации ключевого кадра в ios?

Как настроить анимационную кривую при использовании анимации ключевого кадра UIView:

animateKeyframesWithDuration:delay:options:animations:completion:

Все, что я делаю в блоке анимации, кажется линейным (если я не использую параметр UIViewKeyframeAnimationOptionCalculationModeCubic, но это не то, что я хочу).

Я хочу, чтобы в анимации, как опция UIViewAnimationOptionCurveEaseOut, была легко вырезана кривая, используя регулярную анимацию:

animateWithDuration:delay:options:animations:completion:

Ответ 1

Если вы используете ключевые кадры, вы должны сами определить кривую. Если вы добавляете линейные ключевые кадры, у вас есть линейная анимация. Если вы добавите нелинейные ключевые кадры, у вас будет нелинейная анимация.

frameStartTime - ваш друг здесь... он всегда будет линейным между ключевыми кадрами (или шагами/кубиками/кубиками, как определено в UIViewKeyframeAnimationOptionCalculationMode)

UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 9,
UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 9,
UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 9,
UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 9,
UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 9

Чтобы рассчитать правильные значения времени, вы можете использовать это как ссылку: RBBEasingFunction

например. EaseInOutQuad как это (где t - относительное время в анимации):

if (t < 0.5) {
    return 2 * t * t;
} else {
    return -1 + (4 - 2 * t) * t;
}

Ответ 2

Swift 2.0 не разрешает кастинг UIViewAnimationOptions как UIViewKeyframeAnimationOptions. Это также не позволит | объединить их.

Однако для UIViewKeyframeAnimationOptions существует инициализатор, который принимает rawValue. Итак, следующий код работает, чтобы положить UIViewAnimationOptions в UIViewKeyframeAnimationOptions:

let animationOptions: UIViewAnimationOptions = .CurveEaseOut
let keyframeAnimationOptions: UIViewKeyframeAnimationOptions = UIViewKeyframeAnimationOptions(rawValue: animationOptions.rawValue)

Затем я могу пройти keyframeAnimationOptions до animateKeyframesWithDuration, и все отлично работает.

Ответ 3

Собственно, вы можете использовать те же самые флагов кривой, которые вы используете для animateWithDuration: delay: options: animations: completion:. Просто "двоичный" или "другой" с другими параметрами в вашем вызове animateKeyframesWithDuration: delay: options: animations: completion:

Документация запутанна, но она работает.

Значения кривых, которые вы можете использовать, следующие:

UIViewAnimationOptionCurveEaseInOut = 0 << 16,
UIViewAnimationOptionCurveEaseIn    = 1 << 16,
UIViewAnimationOptionCurveEaseOut   = 2 << 16,
UIViewAnimationOptionCurveLinear    = 3 << 16,

Кривая анимации по умолчанию, которую вы получаете, равна 0, или простота, непринужденность.

Ответ 4

Здесь хорошее и чистое решение Swift, с которым я придумал:

extension UIViewKeyframeAnimationOptions {

    init(animationOptions: UIViewAnimationOptions) {
        rawValue = animationOptions.rawValue
    }

}

Использование:

UIViewKeyframeAnimationOptions(animationOptions: .CurveEaseOut)

Ответ 5

Ответ от @eskimwier не работал у меня при попытке установить кривую на linear для animateKeyframes(withDuration:delay:options:animations:completion:). Это было в Swift 3, Xcode 8.2.1.

Моя анимация по умолчанию не соответствует easeInOut (медленный запуск, быстрее в середине, медленный в конце). Apple изменила кривую по умолчанию?

Во всяком случае, мне нужна линейная кривая, и попробовал предложенный выше подход использовать UIViewAnimationOptions с анимацией ключевого кадра:

let animationOptions: UIViewAnimationOptions = .curveLinear
var keyframeAnimationOptions: UIViewKeyframeAnimationOptions = UIViewKeyframeAnimationOptions(rawValue: animationOptions.rawValue)

UIView.animateKeyframes(withDuration: 3, delay: 0, options: [keyframeAnimationOptions], animations: {
    //... animations here ...
}, completion: nil)

Это не имело никакого эффекта. Единственное, что сработало для меня, это сделать это, прежде чем вызывать animateKeyframes:

UIView.setAnimationCurve(UIViewAnimationCurve.linear)