Почему Webkit / Safari (iOS, macOS) отображает мои SVG-преобразования в другом порядке по сравнению с Blink и Gecko? - PullRequest
1 голос
/ 17 апреля 2020

У меня есть минимальное изображение SVG со значком звездочки:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <defs>
        <style>
        .a {
            fill: red;
            transform-box: fill-box;
            transform-origin: center;
        }
        </style>
    </defs>
    <!-- x = 45 because it's 10px wide and centered around x=50, so x0 == 45, x1 == 55 -->
    <rect class="a" x="45" y="0" width="10" height="100"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate(-45)"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate( 45)"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate(-90)"/>
</svg>

Это корректно отображается в Firefox 75 и Chrome 80, но не Safari на iOS и macOS:

Firefox 75:

enter image description here

Chrome 80:

enter image description here

Safari на iOS 13

Но в Safari transform-origin, по-видимому, игнорируется или применяется не по порядку по сравнению с атрибутом transform="" на каждом из <rect> элементы:

enter image description here

Мне сказали, что в MacOS Safari воспроизводится такое же испорченное изображение (сейчас у меня нет немедленного доступа к MacOS Safari, поэтому Я не могу опубликовать скриншот оттуда, извините).

Я искал в Google, чтобы посмотреть, не хватает ли в Safari / WebKit поддержки transform-box, transform-origin или transform="rotate(deg)" но, насколько я могу судить, все они полностью поддерживаются Safari в течение многих лет - поэтому я не понимаю, почему он применяет преобразования не по порядку и вызывая сломанный рендеринг.

1 Ответ

2 голосов
/ 18 апреля 2020

После манипулирования с SVG в Safari, веб-инспектор Safari действительно , кажется, распознает свойство стиля transform-origin SVG, но фактически не использует его при применении преобразований, что странно (например, использование transform-origin: center; или transform-origin: 0px 0px или transform-origin: 50px 50px не имели никакого эффекта), поэтому исправление заключается в изменении центра вращения с помощью других средств.

Насколько я могу судить, macOS Safari и iOS Safari оба используют transform-origin только для преобразований на основе CSS с использованием свойства transform и не при использовании преобразований на основе атрибутов SVG с использованием transform="" - тогда как Blink и Gecko оба используют transform-origin для обоих преобразования на основе атрибутов и CSS.

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

Один из подходов состоит в добавлении шага translate, чтобы центр вращения центрировался на холсте, затем выполните вращение, затем отмените шаг translate:

transform="translate( 50, 50 ) rotate(45) translate( -50, -50 )"

Примерно так:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
    <rect fill="red"    x="45" y="0" width="10" height="100" />
    <rect fill="blue"   x="45" y="0" width="10" height="100" transform="translate(50,50) rotate(-45) translate(-50,-50)" />
    <rect fill="green"  x="45" y="0" width="10" height="100" transform="translate(50,50) rotate( 45) translate(-50,-50)" />
    <rect fill="orange" x="45" y="0" width="10" height="100" transform="translate(50,50) rotate(-90) translate(-50,-50)" />
</svg>

Лучший подход: использование rotate( angle, x, y ):

Вместо применения начального шага translate к цепочке transform, я видел что функция преобразования rotate поддерживает указание центра вращения с использованием дополнительных аргументов - так что это работает в Safari, Chrome (+ Edge + Opera) и Firefox:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
    <rect fill="red"    x="45" y="0" width="10" height="100" />
    <rect fill="blue"   x="45" y="0" width="10" height="100" transform="rotate(-45, 50, 50)" />
    <rect fill="green"  x="45" y="0" width="10" height="100" transform="rotate( 45, 50, 50)" />
    <rect fill="orange" x="45" y="0" width="10" height="100" transform="rotate(-90, 50, 50)" />
</svg>
...