Проблема с режимом анимации заливки в iOS при изменении ориентации

#css #ios #animation #safari #css-animations

Вопрос:

Я создал анимацию для перемещения элемента в поле зрения, когда пользователь где-то нажимает. Элемент оформлен так, чтобы быть за кадром. Когда анимация запущена, она перемещает элемент на экране и используется animation-fill-mode: forwards для сохранения положения элемента после окончания анимации. При втором щелчке элемент снова отправляется за кадр с другой анимацией.

Проблема в iOS (протестирована на 14.6), когда пользователь поворачивает устройство — по какой-то причине конечные значения не пересчитываются, поэтому элемент оказывается неправильно расположенным на экране. Вы можете видеть это явно, когда запускается анимация «отправить за кадр» — элемент переходит в предполагаемую начальную позицию анимации, которая должна была совпадать с конечной точкой предыдущей анимации. При циклическом воспроизведении анимации скачка нет

На следующем изображении это показано в действии; после поворота устройства обратите внимание, что положение красной рамки находится в неправильном положении: при переходе от портретной к альбомной ориентации коробка находится слишком далеко вправо, при переходе от альбомной к портретной ориентации коробка находится слишком далеко влево. скриншот iphone

Проблема не возникает на Android с Chrome — окно перемещено правильно.

Ниже приведен код, используемый для создания изображения выше.

Это просто ошибка в iOS, или я что-то делаю не так?

Обновление: Похоже, эта проблема на самом деле не ограничивается мобильными устройствами: на рабочем столе Safari при изменении размера окна браузера возникает та же проблема — вместо того, чтобы изменять положение элемента из-за vw единиц измерения, он каким-то образом сдвигает элемент. Chrome и Firefox ведут себя так, как ожидалось.

 <html>

<head>
    <title>animation test</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        label {
            font-size: 24px;
        }
        .elem {
            position: fixed;
            bottom: -40vw;
            left: -40vw;
            transform: rotate3d(0, 0, 1, 45deg);
            transform-origin: 50% 100%;
            width: 30vw;
            height: 43vw;
            background-color: red;
        }

        .anim--in {
            animation: anim-in 1s;
            animation-fill-mode: forwards;
        }

        .anim--out {
            animation: anim-out 1s;
            animation-fill-mode: backwards;
        }

        @keyframes anim-in {
            0% {
                bottom: -40vw;
                left: -40vw;
            }
            100% {
                bottom: -2vw;
                left: -15vw;
            }
        }

        @keyframes anim-out {
            0% {
                bottom: -2vw;
                left: -15vw;
            }
            100% {
                bottom: -40vw;
                left: -40vw;
            }
        }
    </style>
</head>
<body>
    <label><input id="trigger" type="checkbox">Tap me to animate</label>

    <div class="elem"></div>

    <script>
        const trigger = document.getElementById("trigger");
        trigger.addEventListener("click", () => {
            const elem = document.getElementsByClassName("elem")[0];
            if (elem.classList.contains("anim--in")) {
                elem.classList.remove("anim--in");
                elem.classList.add("anim--out");
            } else {
                elem.classList.remove("anim--out");
                elem.classList.add("anim--in");
            }
            console.log("click!");
        });
    </script>
</body>
</html>