Понять и рассчитать анимацию поворота экрана iOS
В iOS есть вот такая анимация поворота экрана при смене ориентации:
По моим наблюдениям здесь происходит следующее: экран поворачивается под прямым углом, одновременно с этим плавно меняется размер видимой области, которая в моем примере выделена красным цветом.
Мне необходимо понять, каким образом рассчитывается размер этой видимой области в процессе анимации.
Есть следующие исходные данные:
duration - продолжительность анимации
targetWidth/targetHeight - размеры экрана после поворота
curentWidth/curentHeight - размеры видимой области в настоящий момент времени
startTime - время начала анимации в миллисекундах
Допустим у нас есть функция, которая будет запускаться максимально часто в процессе анимации (в идеале 60 раз в секунду, но не гарантированно - возможен пропуск кадров), в которой мы должны рассчитать размер видимой области в текущий момент времени. В этой функции есть переменная currentTime в которой хранится текущее время в миллисекундах. Для начала нам надо определить текущий прогресс анимации, пусть это будет число с плавающей точкой от 0 до 1, делаем это так:
progress = (currentTime - startTime) / duration;
Далее следует реализовать логику того, как относительно текущего прогресса будут меняться размеры видимой области. Я взял тут для примера линейную интерполяцию:
lerp(start, end, t) {
return start * (1 - t) + end * t;
}
start - начальное (текущее) значение
end - конечное (целевое) значение
t - прогресс (0..1)
Получается следующая логика:
if (progress <= 1) {
curentWidth = lerp(curentWidth, targetWidth, progress);
curentHeight = lerp(curentHeight, targetHeight, progress);
} else {
// Остановить выполнение
}
При такой реализации происходит следующее:
Размеры видимой области меняются не так как нужно: в портретной ориентации справа, а в альбомной снизу (на примере - справа) видно как моя анимация опережает системную анимацию iOS.
Вопрос в том как точно рассчитать размеры видимой области.
UPD: Для сравнения приведу размеры полученные в ходе системной iOS анимации ([self.view.layer.superlayer presentationLayer] frame]) с помощью CADisplayLink в симуляторе:
- Portrait 320x568 to Landscape 568x320:
width: 320.243 height: 567.757
width: 323.311 height: 564.689
width: 329.032 height: 558.968
width: 338.222 height: 549.778
width: 351.841 height: 536.159
width: 370.106 height: 517.894
width: 385.66 height: 502.34
width: 406.962 height: 481.038
width: 429.834 height: 458.166
width: 453.67 height: 434.33
width: 476.763 height: 411.237
width: 498.749 height: 389.251
width: 517.971 height: 370.029
width: 534.63 height: 353.37
width: 547.756 height: 340.244
width: 557.701 height: 330.299
width: 564.146 height: 323.854
width: 567.481 height: 320.519
width: 568 height: 320
- Landscape 568x320 to Portrait 320x568:
width: 567.768 height: 320.232
width: 564.667 height: 323.333
width: 559.113 height: 328.887
width: 547.701 height: 340.299
width: 535.637 height: 352.363
width: 520.4 height: 367.6
width: 502.572 height: 385.428
width: 481.624 height: 406.376
width: 458.583 height: 429.417
width: 433.508 height: 454.492
width: 411.361 height: 476.639
width: 389.772 height: 498.228
width: 370.197 height: 517.803
width: 353.67 height: 534.33
width: 340.18 height: 547.82
width: 330.549 height: 557.451
width: 323.93 height: 564.07
width: 320.563 height: 567.437
width: 320 height: 568
И аналогичные цифры моих вычислений:
- Portrait 320x568 to Landscape 568x320:
width: 320 height: 568
width: 333.778 height: 554.222
width: 359.802 height: 528.198
width: 394.502 height: 493.498
width: 433.057 height: 454.943
width: 470.541 height: 417.459
width: 503.028 height: 384.972
width: 528.295 height: 359.705
width: 545.941 height: 342.059
width: 556.971 height: 331.029
width: 563.098 height: 324.902
width: 566.094 height: 321.906
width: 567.365 height: 320.635
width: 567.823 height: 320.177
width: 567.961 height: 320.039
width: 567.993 height: 320.007
width: 567.999 height: 320.001
width: 568 height: 320
width: 568 height: 320
- Landscape 568x320 to Portrait 320x568:
width: 568 height: 320
width: 554.222 height: 333.778
width: 528.198 height: 359.802
width: 493.498 height: 394.502
width: 454.943 height: 433.057
width: 417.459 height: 470.541
width: 384.972 height: 503.028
width: 359.705 height: 528.295
width: 342.059 height: 545.941
width: 331.029 height: 556.971
width: 324.902 height: 563.098
width: 321.906 height: 566.094
width: 320.635 height: 567.365
width: 320.177 height: 567.823
width: 320.039 height: 567.961
width: 320.007 height: 567.993
width: 320.001 height: 567.999
width: 320 height: 568
width: 320 height: 568

