CSS3转换顺序很重要:最先操作

时间:2014-12-24 10:19:22

标签: css css3 transform css-transforms

当我们使用CSS3 transform: operation1(...) operation2(...)时,先完成哪一个?

第一个操作似乎是右侧中最多的一个。,即此operation2operation1之前完成。 只是为了确定,这是真的吗?

注意:我在某些地方读过一件事,反之亦然(答案,互联网上的文章),这就是问题所在。

4 个答案:

答案 0 :(得分:31)

是的,完成的第一个操作是右侧最多的操作。即operation2 operation1之前完成。

以下是文档:http://www.w3.org/TR/css-transforms-1/但我还没有找到关于此的段落。


示例1

此处缩放完成首先然后垂直翻译100px(如果先完成翻译,缩放将使500px的翻译!)



#container { 
  	position: absolute; 
  	transform: translate(0,100px) scale(5); 
  	transform-origin: 0 0; }

<div id="container"><img src="https://i.stack.imgur.com/xb47Y.jpg"></img></div>
&#13;
&#13;
&#13;

示例2

此处翻译完成首先然后缩放(在之后完成缩放使翻译看起来像500px翻译!)

&#13;
&#13;
#container { 
  	position: absolute; 
  	transform: scale(5) translate(0,100px); 
  	transform-origin: 0 0; }
&#13;
<div id="container"><img src="https://i.stack.imgur.com/xb47Y.jpg"></img></div>
&#13;
&#13;
&#13;

答案 1 :(得分:3)

转换执行从左到右。变换对应于矩阵运算,这些运算从左到右执行。

背后有直觉,不仅仅是这在规范中作为规范性规则(第3点:https://drafts.csswg.org/css-transforms-1/#transform-rendering

这是一支可以尝试的笔:https://codepen.io/monfera/pen/YLWGrM

说明:

每个变换步骤都建立自己的坐标系。所以

transform: translateX(500px);

沿其父级的X轴建立一个新的坐标系500px,该元素将在那里渲染。

类似地,

background-color: blue;
transform: translateX(500px) rotate(60deg);

首先沿着其父级的X轴(右侧)建立一个新的坐标系500px,然后只建立,在其内部(已翻译,但它现在不相关)坐标系它是否执行旋转。所以它是一个向右旋转500px的形状,然后旋转到位(在所谓的transform-origin周围,在本地坐标系中解释,默认为50%50%对于旋转意味着,围绕矩形的中心旋转,但它是旁边的。)

相反的顺序

background-color: orange;
transform: rotate(60deg) translateX(500px);

首先建立一个相对于父级旋转60度的新坐标系,然后沿着现在旋转的坐标系的X轴平移100px,方向不是实际上从文档(或用户)的全局角度来看是正确的。所以,在这种情况下,就像你先旋转纸张一样,然后沿纸张侧面(从原点,在这种情况下是左上角)滑动500个单位的形状。

enter image description here

要进行更高级的讨论,并了解如何直观地理解这两个方向,请查看Composing Transformations - CSS变换遵循后乘法模型,因此请查找包含标题&#34;将转换视为转换局部坐标系&#34; (插图似乎有点偏离)

Local coordinate frame - post-multiply

答案 2 :(得分:0)

我刚刚使用 CSS 转换在 HTML 中创建了一个 3d 房间的演示。我为后墙制作了一个 200x200 DIV,将它留在那个位置。然后我从相同的大小和位置开始做了一个左墙,然后添加

变换:translate3d(-100px,0px,100px)rotateY(90deg)。

然后我做了一个右墙并添加

变换:translate3d(100px,0px,100px)rotateY(90deg)。

这正确地创建了房间。但这是 Safari 13 版。本来我试着先列出旋转步骤,但墙在一个奇怪的位置。所以我看到了从右到左的行为。

答案 3 :(得分:-1)

在其他答案和评论中已经提到了这一点,但我认为没有足够强调:简短的答案是两种方法都是有效的

这完全取决于您是否考虑将坐标附加到元素上(从左到右)还是根据初始元素位置(从右到左)固定到页面上。

这里有一篇文章展示了动画的区别(这使它更容易理解):Chaining transforms

以下是显示文章动画的摘录:

html, body { height: 100%; }
body {
  background: #aaa;
  color: #000;
  font-family: Calibri,Candara,Segoe,"Segoe UI",Optima,Arial,sans-serif;
  overflow: hidden;
  margin: 0;
}
.info {
  text-align: center;
  font-family: Consolas,monaco,monospace;
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 4px;
  color: #fff;
}
.split { white-space: nowrap; }
.side {
  display: inline-block;
  width: 50%;
}
.label {
  text-align: center;
  font-size: 20px;
}
.container {
  position: relative;
  font-size: 50px;
  margin: .6em auto 0;
  width: 0; height: 0;
  transform: translateX(-1em);
}
.ltr .object {
  position: absolute;
  left: 0; top: 0;
  width: 1em; height: 1em;
  margin: -.5em 0 0 -.5em;
  background: rgb(114,34,34);
  animation: ltrObj 5s infinite;
}
@keyframes ltrObj {
  from, 10% { transform: rotate( 0deg) translateX(0em); }
  40%       { transform: rotate(45deg) translateX(0em); }
  70%, to   { transform: rotate(45deg) translateX(2em); }
}
.object.shadow {
  animation: none;
  opacity: .2;
}

.ltr .axes {
  position: absolute;
  left: .5em; top: .5em;
  width: 1em; height: 1em;
  color: #111;
  box-sizing: border-box;
  border-left: 2px solid;
  border-top: 2px solid;
}
.ltr .axes::before, .ltr .axes::after {
  content: '';
  position: absolute;
  width: .2em; height: .2em;
  box-sizing: border-box;
  border-left: 2px solid;
  border-top: 2px solid;
  transform-origin: top left;
}
.ltr .axes::before { top: 100%; left: 0; margin-left: -1px; margin-top: 1px; transform: rotate(225deg); }
.ltr .axes::after { top: 0; left: 100%; margin-top: -1px; margin-left: 1px; transform: rotate(135deg); }

.rtl .axes {
  position: absolute;
  left: 0; top: 0;
  width: 2.5em; height: 2.3em;
  color: #111;
  box-sizing: border-box;
  border-left: 2px solid;
  border-top: 2px solid;
}
.rtl .axes::before, .rtl .axes::after {
  content: '';
  position: absolute;
  width: .2em; height: .2em;
  box-sizing: border-box;
  border-left: 2px solid;
  border-top: 2px solid;
  transform-origin: top left;
}
.rtl .axes::before { top: 100%; left: 0; margin-left: -1px; margin-top: 1px; transform: rotate(225deg); }
.rtl .axes::after { top: 0; left: 100%; margin-top: -1px; margin-left: 1px; transform: rotate(135deg); }

.rtl .object {
  position: absolute;
  left: 0; top: 0;
  width: 1em; height: 1em;
  margin: -.5em 0 0 -.5em;
  background: rgba(100,0,0,0.8);
  animation: rtlObj 5s infinite;
}
@keyframes rtlObj {
  from, 10% { transform: rotate( 0deg) translateX(0em); }
  40%       { transform: rotate( 0deg) translateX(2em); }
  70%, to   { transform: rotate(45deg) translateX(2em); }
}

.helper-mask {
  position: absolute;
  left: 0; top: 0;
  width: 3em; height: 3em;
  overflow: hidden;
}
.helper {
  position: absolute;
  left: 0; top: -2em;
  width: 0; height: 2em;
  margin-top: 2px;
  box-sizing: border-box;
  border: 2px solid #00c;
  border-left: none;
  border-radius: 0 100% 0 0;
  transform-origin: bottom left;
  animation: helper 5s infinite;
}
@keyframes helper {
  from, 10% { width: 0em; transform: rotate( 0deg); }
  40%       { width: 2em; transform: rotate( 0deg);}
  70%, to   { width: 2em; transform: rotate(45deg);}
}
<div class="info">rotate(45deg) translateX(2em)</div>
<div class="split">
  <div class="side ltr">
    <div class="label">Left to Right</div>
    <div class="container">
      <div class="object shadow"></div>
      <div class="object">
        <div class="axes"></div>
      </div>
    </div>
  </div>
  <div class="side rtl">
    <div class="label">Right to Left</div>
    <div class="container">
        <div class="axes"></div>
        <div class="object"></div>
        <div class="helper-mask">
            <div class="helper"></div>
        </div>
    </div>
  </div>
</div>

实际的实现方式与从左到右还是从右到左无关紧要,只要您牢记差异,两者在创建动画时都同样有效。