матрица не равна переводить и вращать комбинацию в анимации преобразования CSS? - PullRequest
0 голосов
/ 28 декабря 2018

@keyframes gray {
  0% { transform: matrix(1, 0, 0, 1, 0, 0) }
  100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
  0% { transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px); }
  100% { transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px); }
}
.gray {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: gray;
  transform-origin: 0px 0px;
  animation: gray linear 1s infinite;
}
.lightblue {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: lightblue;
  transform-origin: 0px 0px;
  animation: lightblue linear 1s infinite;
}
  <div class="gray"></div>
  <div class="lightblue"></div>

Как я знаю

transform: matrix(1, 0, 0, 1, 0, 0);

равно

transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px);

и

transform: matrix(-1, 0, 0, -1, 20, 20)

равно

transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px);

, когда я использую вышеуказанное правило css непосредственно для элемента, все работаетхорошо.но после того, как я использую вышеуказанное правило css в ключевых кадрах, все идет не так.угол поворота серого элемента отличается от угла наклона светло-синего цвета.

Я тестирую код в хроме 71

1 Ответ

0 голосов
/ 28 декабря 2018

Проблема в том, как браузер будет обрабатывать интерполяцию.Обе матрицы в порядке, и они совпадают с определенным преобразованием, но интерполяция между ними не одинакова.

Используйте вперед, а не бесконечно, чтобы увидеть, что оба начнут и закончатся в одном и том же состоянии:

@keyframes gray {
  0% { transform: matrix(1, 0, 0, 1, 0, 0) }
  100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
  0% { transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px); }
  100% { transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px); }
}
.gray {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: gray;
  transform-origin: 0px 0px;
  animation: gray linear 2s 0.5s forwards;
  border-right:2px solid;
}
.lightblue {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: lightblue;
  transform-origin: 0px 0px;
  animation: lightblue linear 2s 0.5s forwards;
  border-right:2px solid;
}
<div class="gray"></div>
  <div class="lightblue"></div>

По сути, матрица сначала разлагается на преобразование, а затем интерполируется.поэтому первый matrix(1, 0, 0, 1, 0, 0), который является тождеством, будет преобразован в нулевое преобразование (например, scale(1,1) или rotate(0)), а не translate(10px, 10px) rotate(0deg) translate(-10px, -10px), как вы можете подумать.затем второй matrix(-1, 0, 0, -1, 20, 20) может быть преобразован в scale(-1,-1) translate(-20px,-20px).Опять же, это не будет translate(10px, 10px) rotate(180deg) translate(-10px, -10px).

Теперь ясно, что интерполяция (промежуточные состояния) не будет одинаковой для обеих анимаций.Это связано с тем, что браузер не будет использовать те же преобразования, которые вы использовали для определения матрицы.Теоретически, существует бесконечное количество комбинаций, и браузер будет использовать свой собственный алгоритм для поиска того, который он будет использовать, который не обязательно будет тем, который вы определили.

Вы можете проверить эту ссылку для более подробной информации:https://drafts.csswg.org/css-transforms/#interpolation-of-transforms

Вот пример того, как мы можем сделать то же самое:

@keyframes gray {
  0% { transform: matrix(1, 0, 0, 1, 0, 0) }
  100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
  0% { transform: scale(1,1) }
  100% { transform:scale(-1,-1) translate(-20px, -20px)  ; }
}
.gray {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: gray;
  transform-origin: 0px 0px;
  animation: gray linear 2s 0.5s infinite;
  border-right:2px solid;
}
.lightblue {
  float: left;
  margin-left: 50px;
  width: 20px;
  height: 20px;
  background: lightblue;
  transform-origin: 0px 0px;
  animation: lightblue linear 2s 0.5s infinite;
  border-right:2px solid;
}
<div class="gray"></div>
  <div class="lightblue"></div>
...