Почему transform-origin не работает для Firefox с использованием встроенного SVG и есть ли альтернатива? - PullRequest
1 голос
/ 07 февраля 2020

Я обнаружил несоответствия в Firefox по сравнению с Chrome, Edge и Opera. Каждый браузер прекрасно обрабатывает transform-origin при использовании класса CSS. Однако, когда я помещаю transform-origin в элемент SVG в качестве атрибута, FF игнорирует эффект. Демо-код ниже. Мой главный вопрос - как обойти это, но мне также любопытно узнать, является ли это ожидаемым поведением.

CSS transform-origin работает в FF.

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>	
	<style>	
		.centered{			
			transform-origin: center;
		}
	</style>
	<path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' class='centered'/>
</svg>

Встроенный SVG, похоже, не распознает transform-origin (работает последовательно в Chrome / edge)

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>	
	<path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' transform-origin='center'/>
</svg>

Редактировать: Другой пользователь указал, что этот вопрос похож на Как установить начало преобразования в SVG , но их предпосылка очень широка ( как) и либо неправильный, либо устаревший (опубликовано 8,5 лет go).

"Я пытался использовать атрибут transform-origin, но он ни на что не влияет."

Возможно, поддержка браузера улучшилась, но мой вопрос показывает, что transform-origin прекрасно работает как правило CSS во всех современных браузерах или как атрибут представления во всех современных браузерах, кроме FireFox. Эта дифференциация, вероятно, привела к тому, что одно решение является уникальным для этой темы, а второе решение, которое является новым подходом к другим потокам, отвечает.

Не говоря уже о том, что их вопрос сосредоточен вокруг реализации JavaScript и был опубликован в то время, когда FireFox не распознавал ключевые слова, такие как "центр" или числа без единиц, что отвлекает от основной проблемы разметки SVG, которая заключается в том, что FireFox интерпретирует атрибут представления transform-origin='', отличный от других браузеров.

Ответы [ 2 ]

2 голосов
/ 08 февраля 2020

В целом ответ отмечен правильно, работает во всех случаях. Однако я пишу другое решение, потому что оно самое простое в реализации. Но учтите, что это работает только для transform, а не для patternTransform. Хотя не-FireFox браузеры распознают transform-origin для обоих атрибутов, мое решение не работает для patternTransform на FireFox.

Добавление transform-origin в атрибут стиля (style='transform-origin:center') вместо этого своего собственного атрибута представления (transform-origin='center') работает для transform, как показано ниже. Это даже работает для SVG в URI данных.

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>    
    <path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' style='transform-origin:center'/>
</svg>
1 голос
/ 07 февраля 2020

Я решил проблему, но я (пока) не могу дать вам исчерпывающего объяснения, почему она работает.

Первое, что нужно знать, это то, что вы можете цепочка SVG-преобразования .

Итак, где бы вы ни писали transform="scale(2)", вы можете добавить translate(x, y) в цепочку, например:

transform="scale(2) translate(x, y)"

Пока что, так хорошо ... но если scale равно 2, то какие значения мы должны дать x и y из translate?

Чтобы выяснить, я решил наложить большее и добавьте меньшие масштабированные версии вашей SVG-фигуры (по одной для каждого цвета радуги) и посмотрите, какие образцы я смог найти.

Поверх вашей серой фигуры я поместил идентичный размер зеленая форма.

Я дал зеленую форму преобразование:

transform="scale(1) translate(0, 0)"

, чтобы оно было в точности совпадать с вашим оригиналом серый форма.

Затем я приступил к наложению крупномасштабных версий ( желтый , оранжевый , красный ) и наложение меньших масштабированных версий ( синий , инди go, фиолетовый ).

Я предсказал что x и y в каждом случае будут относиться к коэффициенту scale, применяемому к этой форме, а также к общему размеру исходного viewBox.

С 3 меньшими версиями и 3 большими версиями возникла модель:

  • Красный , 8 больше / x & y Значение преобразования 50% of ((1000 / 8) - 1000)
  • Оранжевый , * в 1071 * раз больше / x & y Значение преобразования 50% of ((1000 / 4) - 1000)
  • Желтый , 2 раз больше / x & y значение преобразования 50% of ((1000 / 2) - 1000)
  • Зеленый , 1 больше / x & y значение преобразования 50% of ((1000 / 1) - 1000)
  • Синий , * в 1095 * раз больше / x & y Значение преобразования 50% of ((1000 / 0.5) - 1000)
  • Инди go, 0.25 раз как большое / x & y значение преобразования равно 50% of ((1000 / 0.25) - 1000)
  • Фиолетовый , * 1 В 111 * раз больше / x & y значение преобразования равно 50% of ((1000 / 0.125) - 1000)

Исходя из этого, мы можем заключить, что если вы располагаете фигуру с центром в 50%, 50% вашего viewBox и вы хотите отобразить фигуру в той же позиции с помощью scale(2), вы должны также применить translate для x из:

50% of ((width of canvas / scale-factor) - (width of canvas))

где 50% соответствует позиции x, по которой вы хотите центрировать фигуру.

И translate для y из:

50% of ((height of canvas / scale-factor) - (height of canvas))

, где 50% соответствует y положение, в котором вы хотите центрировать фигуру.

Это работает последовательно, но я еще не потратил достаточно времени на его изучение, чтобы правильно понять, почему.

Рабочий пример :

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">

<!-- Grey Original -->
<path fill="#555" d="M500 500 400 400 400 600 600 600 600 400z" />

<!-- Red Transform [50% of ((1000 / 8) - 1000) is -437.5] -->
<path fill="rgb(255, 0, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(8) translate(-437.5, -437.5)" />

<!-- Orange Transform [50% of ((1000 / 4) - 1000) is -375] -->
<path fill="rgb(255, 125, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(4) translate(-375, -375)" />

<!-- Yellow Transform [50% of ((1000 / 2) - 1000) is -250] -->
<path fill="rgb(255, 255, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(2) translate(-250, -250)" />

<!-- Green Transform [50% of ((1000 / 1) - 1000) is 0] -->
<path fill="rgb(0, 125, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(1) translate(0, 0)" />

<!-- Blue Transform [50% of ((1000 / 0.5) - 1000) is 500] -->
<path fill="rgb(0, 0, 125)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.5) translate(500, 500)" />

<!-- Indigo Transform [50% of ((1000 / 0.25) - 1000) is 1500] -->
<path fill="rgb(63, 0, 255)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.25) translate(1500, 1500)" />

<!-- Violet Transform [50% of ((1000 / 0.125) - 1000) is 3500] -->
<path fill="rgb(199, 125, 243)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.125) translate(3500, 3500)" />

</svg>
...