Почему этот переход работает по-разному в Chrome и Firefox?

У меня есть следующая анимация SVG (это довольно большой фрагмент, см. «Показать фрагмент кода»):

.logo > .logo-compass-frame {
  fill: none;
  stroke: black;
  stroke-width: 15;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north, .logo > .logo-compass-south {
  stroke: black;
  stroke-width: 8;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-south {
  fill: none;
}

.logo > .logo-compass-center {
  fill: black;
  stroke: black;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north, .logo > .logo-compass-south, .logo > .logo-compass-center {
  transition: 0.5s ease-in-out;
  opacity: 1;
}

.logo:hover > .logo-compass-north, .logo:hover > .logo-compass-south {
  transform-origin: center;
}

.logo:hover > .logo-compass-north {

  transform: rotate(90deg) scale(1.5) translate(10px);
}

.logo:hover > .logo-compass-south {
  transform: rotate(90deg) scale(1.5) translate(-10px);
}

.logo:hover > .logo-compass-center {
  opacity: 0;
}
<svg class="logo" x="0px" y="0px" viewBox="0 0 272.6 272.6">
  <circle class="logo-compass-frame" cx="136.3" cy="136.3" r="105.8" />
  <polygon class="logo-compass-north" points="138,63.6 123.8,110.5 138,134.5 152.2,110.5" />
  <polygon class="logo-compass-south" points="138,209 152.2,162.1 138,138.1 123.8,162.1" />
  <circle class="logo-compass-center" cx="138" cy="136.6" r="5.7" />
</svg>

Проблема в том, что он действует по-разному только в Firefox (не тестировался в Edge или IE, так как я работаю в macOS). Для браузеров WebKit и Opera я получаю:

Хром 60.0.3112.90:

Сафари 10.1:

Опера 47.0.2631.39:

Фаерфокс 54.0.1:

Происходит что-то подозрительное. Я не пробовал Edge или IE, так что, может быть, это какая-то проблема соответствия спецификации CSS? Я думал, что transform-origin не поддерживается, так как это экспериментальная технология, но добавление -moz-transform-origin ничего не дало, а MDN сообщает, что transform-origin теперь поддерживается.

Почему переходы ведут себя по-разному в разных браузерах и можно ли это исправить?


person Andrew Li    schedule 12.08.2017    source источник


Ответы (1)


Вы не можете прямо сейчас использовать процентные значения для transform-origin, потому что процентные значения обрабатываются по-разному в Chrome и Firefox. Это также относится к псевдозначениям, таким как «центр», который определен как эквивалентный «50%».

Вместо этого вам нужно использовать абсолютные значения пикселей, чтобы обеспечить совместимость с разными браузерами.

.logo > .logo-compass-frame {
  fill: none;
  stroke: black;
  stroke-width: 15;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north, .logo > .logo-compass-south {
  stroke: black;
  stroke-width: 8;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-south {
  fill: none;
}

.logo > .logo-compass-center {
  fill: black;
  stroke: black;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north, .logo > .logo-compass-south, .logo > .logo-compass-center {
  transition: 0.5s ease-in-out;
  opacity: 1;
}

.logo:hover > .logo-compass-north {
  transform-origin: 138px 99px;
}

.logo:hover > .logo-compass-south {
  transform-origin: 138px 173.5px;
}

.logo:hover > .logo-compass-north {

  transform: rotate(90deg) scale(1.5) translate(10px);
}

.logo:hover > .logo-compass-south {
  transform: rotate(90deg) scale(1.5) translate(-10px);
}

.logo:hover > .logo-compass-center {
  opacity: 0;
}
<svg class="logo" x="0px" y="0px" viewBox="0 0 272.6 272.6">
  <circle class="logo-compass-frame" cx="136.3" cy="136.3" r="105.8" />
  <polygon class="logo-compass-north" points="138,63.6 123.8,110.5 138,134.5 152.2,110.5" />
  <polygon class="logo-compass-south" points="138,209 152.2,162.1 138,138.1 123.8,162.1" />
  <circle class="logo-compass-center" cx="138" cy="136.6" r="5.7" />
</svg>

Обновить

Я выяснил, почему Firefox ведет себя по-другому. Это не ошибка. Firefox на самом деле правильный. Это потому, что Firefox правильно интерпретирует спецификацию, а другие браузеры — нет.

Прямая причина связана с тем, что мы указывали transform-origin в правиле :hover. Таким образом, исходная точка также интерполировалась (т.е. перемещалась). Исправление заключается в следующем:

  1. Укажите, что мы хотим только передать свойство преобразования.

    transition: transform 0.5s ease-in-out;
    
  2. Или переместите transform-origin из правила наведения.

Ниже представлена ​​обновленная версия, в которой используется подход №2.

.logo > .logo-compass-frame {
  fill: none;
  stroke: black;
  stroke-width: 15;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north {
  stroke: black;
  stroke-width: 8;
  transform-origin: 138px 99px;
}

.logo > .logo-compass-south {
  stroke: black;
  stroke-width: 8;
  fill: none;
  transform-origin: 138px 173.5px;
}

.logo > .logo-compass-center {
  fill: black;
  stroke: black;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-miterlimit: 10;
}

.logo > .logo-compass-north, .logo > .logo-compass-south, .logo > .logo-compass-center {
  transition: 0.5s ease-in-out;
  opacity: 1;
}

.logo:hover > .logo-compass-north {
  transform: rotate(90deg) scale(1.5) translate(10px);
}

.logo:hover > .logo-compass-south {
  transform: rotate(90deg) scale(1.5) translate(-10px);
}

.logo:hover > .logo-compass-center {
  opacity: 0;
}
<svg class="logo" width="300px" viewBox="0 0 272.6 272.6">
  <circle class="logo-compass-frame" cx="136.3" cy="136.3" r="105.8" />
  <polygon class="logo-compass-north" points="138,63.6 123.8,110.5 138,134.5 152.2,110.5" />
  <polygon class="logo-compass-south" points="138,209 152.2,162.1 138,138.1 123.8,162.1" />
  <circle class="logo-compass-center" cx="138" cy="136.6" r="5.7" />
</svg>

person Paul LeBeau    schedule 12.08.2017
comment
Ах да. Я подозревал, что transform-origin, но я забыл, что center был просто псевдонимом для процентных значений, а FF еще не полностью поддерживает это. Спасибо! - person Andrew Li; 12.08.2017
comment
Кроме того, как именно вы рассчитали значения пикселей? На самом деле мой логотип находится на панели навигации. - person Andrew Li; 12.08.2017
comment
Я нахожу центр, открывая инструменты разработчика и выбирая интересующий элемент с помощью инструмента выбора элементов. Затем в консоли набираю: var b=$0.getBBox();. Затем b.x+b.width/2 и b.y+b.height/2. - person Paul LeBeau; 12.08.2017
comment
@AndrewLi FF действительно полностью поддерживает это. Это Chrome ошибается. Поведение Chrome/Opera планируется согласовывать с Firefox и спецификацией w3c, а не наоборот. - person Robert Longson; 12.08.2017
comment
Есть ли какой-нибудь приемлемый способ сохранить мою текущую анимацию или переписать ее, чтобы она соответствовала спецификации, но выглядела так же? - person Andrew Li; 13.08.2017
comment
@AndrewLi Я не могу объяснить оставшееся странное поведение в Firefox. Похоже, это ошибка в том, как трансформация интерполируется в анимацию. Я собираюсь провести расследование. - person Paul LeBeau; 13.08.2017
comment
@PaulLeBeau Большое спасибо! - person Andrew Li; 13.08.2017