2017-02-12 2 views
2

Используя этот код:Как устранить «прыжок» в моей CABasicAnimation?

func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) { 
    let multiplier = (isClockwise ? 1 : -1) 
    let key = (isClockwise ? "Spin" : "Rotate") 
    var rotation: CABasicAnimation? 
    rotation = CABasicAnimation(keyPath: "transform.rotation") 
    rotation!.fromValue = Int(0) 
    let multiplicand = multiplier * 2 
    rotation!.toValue = Int(Double(multiplicand) * .pi) 
    rotation!.duration = 30 // Speed 
    rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever. 
    aView.layer.add(rotation!, forKey: key) 
} 

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

Однако, когда 30 секунд (продолжительность) составляет, есть мерцание, как вид переходит обратно к тому, как он выглядел до анимации.

Я понимаю, что это должно работать таким образом.

Как применить поворот к изображению «раньше», чтобы, когда продолжительность истекает, я не вижу, чтобы какие-либо ячейки прыгали?

Увеличение длительности анимации замедляет вращение рулем, так что не является подходящим решением.

Если #22521690 относится, я не понимаю, как - у меня нет явного CATransaction.

+1

Почему вы объявляете 'rotation' как необязательный? – matt

+0

Да, мне нужно его очистить. Я преобразовал это из цели c пару лет назад. Я только недавно просмотрел его. – Mozahler

+0

Обновлен мой источник. Спасибо, что указали! – Mozahler

ответ

2

Попробуйте

rotation!.toValue = Double(multiplicand) * .pi 

вместо

rotation!.toValue = Int(Double(multiplicand) * .pi) 

Проблема заключается с радиан точностью, которая теряется в результате преобразования Int.

+0

Wow !!! Бесконечно благодарен! – Mozahler

+0

в любое время! то, что сказал Мэтт и Дункан, верно. но в вашем случае его полное вращение и начальное и конечное состояние одинаковы. Поэтому вам не нужно сбросить значения –

+0

Хороший улов. Я должен был внимательно рассмотреть эту часть. Я думал, что преобразование Int в toValue было странным, но не переставало думать. –

2

На следующей строке после применения анимации к слою установите свойство, которое вы анимируете, до его конечного значения.

Поскольку анимация «в полете», нормальное отображение слоя покрыта презентационного слоя, специальный слой анимации.

После завершения анимации, презентации слой скрыт/удален, а фактический слой подвергается. Если это то же состояние, что и уровень представления в конце анимации, тогда нет перехода.

Этот код может выглядеть следующим образом:

func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) { 
    let multiplier = (isClockwise ? 1 : -1) 
    let key = (isClockwise ? "Spin" : "Rotate") 
    var rotation: CABasicAnimation? 
    rotation = CABasicAnimation(keyPath: "transform.rotation") 
    rotation!.fromValue = 0.0 
    let multiplicand = multiplier * 2 
    let finalAngle = Double(multiplicand) * .pi 
    rotation!.toValue = finalAngle 
    rotation!.duration = 30 // Speed 
    rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever. 
    aView.layer.add(rotation!, forKey: key) 

    //------------------- 
    //Set the final transform on the layer to the final rotation, 
    //but without animation 
    CATransaction.begin() 
    CATransaction.setDisableActions(true) 
    let finalTransform = CATransform3DMakeRotation(CGFloat(finalAngle), 0.0, 0.0, 1.0) 
    aView.layer.transform = finalTransform 
    CATransaction.commit() 
    //------------------- 
} 
+0

Это именно то, что я не знаю, как это сделать: указать конечное значение для слоя. – Mozahler

+0

См. Изменение в моем ответе. –

+0

@matt, хороший пункт. Я забыл эту прекрасную, запутанную деталь. –

Смежные вопросы