Странное поведение при вращении элемента при наведении - PullRequest
0 голосов
/ 01 октября 2018

С учетом этих двух примеров.

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

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  transform: translateX(-50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: translateX(-50%) rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

Использование анимации

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transform: translateX(-50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
  animation: rotate 2s linear 2s;
}

@keyframes rotate {
  to {
    transform: translateX(-50%) rotate(var(--deg));
  }
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

Как видите, rotate(180deg) и rotate(-180deg) действуют одинаково и rotate(360deg) вообще не движется.

Проблема в том, что если он будет двигаться постепенно, он будет действовать нормально.

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  animation: rotate 2s linear;
}

@keyframes rotate {
  0% {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  25% {
    transform: translate(-50%, -50%) rotate(45deg);
  }
  50% {
    transform: translate(-50%, -50%) rotate(90deg);
  }
  75% {
    transform: translate(-50%, -50%) rotate(135deg);
  }
  100% {
    transform: translate(-50%, -50%) rotate(180deg);
  }
}
<div></div>

Решение, которое я нашел, заключается в замене translate(-50%, -50%) на margins, что не соответствует

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  /* Minus half the width, hard coded not a good idea*/
  margin: 0 0 0 -75px; 
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

Итак, главный вопрос: почему происходит такое странное поведение?

РЕДАКТИРОВАТЬ: не требуется быстрый ответ (как вы можете видеть, есть два варианта), но есть и объяснение:)

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Кажется, это ошибка браузера (по крайней мере, в Chrome), так как она работает нормально, если вы попробуете код на Firefox.

Позвольте обратиться к спецификации , чтобы объяснить это.Вот все разные случаи того, как должна работать интерполяция между преобразованиями.

enter image description here

В нашем случае мы рассмотрим последнюю точку, где мы не делаемиметь одинаковое количество функций преобразования, и браузер должен обработать это, добавив функцию преобразования идентификаторов из отсутствующего списка, и в нашем случае это должно быть rotate(0).

Так что технически переход от translate(-50%) к translate(-50%) rotate(360deg) должен совпадать с переходом от translate(-50%) rotate(0) к translate(-50%) rotate(360deg).

Если я что-то упустил, это точноошибка, как в случае, когда rotate(360deg) используется один, Chrome обрабатывает этот штраф, используя вторую точку (когда одно значение равно none), которая почти совпадает с последней точкой.

0 голосов
/ 01 октября 2018

Вам нужно установить начальное значение rotate(0), чтобы между двумя состояниями была анимация.Установите начальное преобразование div в:

transform: translateX(-50%) rotate(0);

Переход:

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  transform: translateX(-50%) rotate(0);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: translateX(-50%) rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}

body {
  overflow: hidden;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

Анимация:

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transform: translateX(-50%) rotate(0);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
  animation: rotate 2s linear 2s forwards;
}

@keyframes rotate {
  to {
    transform: translateX(-50%) rotate(var(--deg));
  }
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}

body {
  overflow: hidden;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>
...