【问题标题】:matrix not equal to translate and rotate combination in css transform animation?矩阵不等于css变换动画中的平移和旋转组合?
【发布时间】:2018-12-28 18:48:18
【问题描述】:

@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 规则后,事情就出错了。 灰色元素的旋转角度与浅蓝色元素不同。

我在 chrome 71 中测试代码

【问题讨论】:

    标签: css css-animations css-transforms keyframe


    【解决方案1】:

    问题在于浏览器将如何处理插值。两个矩阵都很好,它们与定义的变换相同,但两者之间的插值不一样。

    使用forwards而不是infinite来查看两者将以相同的状态开始和结束:

    @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) 是indentity 将被转换为空转换(例如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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 2014-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多