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

pieyvz9o  于 2023-06-07  发布在  CSS3
关注(0)|答案(5)|浏览(779)

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

第一个操作似乎是最 * 在右边的一个。这里operation2operation1之前完成。”””只是为了确定,这是真的吗?**

  • 注意:我在一些地方读到了一件事和它的相反(答案,互联网上的文章),因此这里的问题。
3z6pesqy

3z6pesqy1#

是的,第一个操作是右边最大的操作,即。这里operation2operation1之前完成。
这个MDN article确实声明:
变换函数按从左到右的顺序相乘,这意味着 * 复合变换按从右到左的顺序有效地应用 *。
以下是文档:http://www.w3.org/TR/css-transforms-1/

示例1

在这里,缩放是 * 首先 * 完成的,* 然后 * 垂直平移100 px(如果先进行平移,缩放将平移500 px!)

#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>

示例二

这里的翻译是 * 第一 然后 * 缩放(缩放 * 后 * 做的翻译看起来像500 px的翻译!)

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

uttx8gqw2#

这一点在其他回答和评论中已经提到,但在我看来没有得到足够的强调:简单的答案是两种方式都有效
这完全取决于您是否考虑到您的坐标附加到您的元素(从左到右),还是基于初始元素位置(从右到左)固定到页面。
这里有一篇文章展示了动画的区别(这使得它更容易理解):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>

实际的实现是使用从左到右还是从右到左是无关紧要的,在创建动画时两者都是同样有效的,只要记住区别。

iq0todco

iq0todco3#

转换执行从左到右。变换对应于矩阵运算,并且这些从左到右执行。
它背后有直觉,这不仅仅是规范中的规范规则(这里的第3点:https://drafts.csswg.org/css-transforms-1/#transform-rendering)
这里有一支笔可以试试:https://codepen.io/monfera/pen/YLWGrM
说明:
每个变换步骤都建立自己的坐标系。所以呢

transform: translateX(500px);

沿着其父元素的X轴建立一个新的坐标系500 px,元素将在那里呈现。
同样地,

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

首先沿着父对象的X轴(向右)建立一个新的坐标系500 px,然后 * 才在该坐标系(已平移,但现在不相关)内执行旋转。因此,它将是一个向右500 px的形状,并在适当的位置旋转(围绕所谓的transform-origin,在局部坐标系中解释,默认的50% 50%旋转意味着围绕矩形中心旋转,但这是一个旁白)。
相反的顺序

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

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

对于更高级的讨论,以及如何直观地理解它的两个方向,请查看Composing Transformations- CSS转换遵循后乘法模型,因此请查找标题为“将转换视为转换局部坐标框架”的页面(插图似乎有点偏离)

xxls0lw8

xxls0lw84#

它首先应用最左边的变换。

如上图所示,与第二个变换相比,第一个变换需要更长的距离。原因是第一个示例首先经历scale,然后根据x轴上的新宽度采用translate指定的距离。因为它现在更宽了,50%将导致它需要更长的距离。由50%指定的测量值是通过取其自身宽度的一半来计算的。
the site I cited from

xtfmy6hx

xtfmy6hx5#

我刚刚使用CSS转换在HTML中创建了一个3D房间的演示。我做了一个200 x200 DIV的后墙,离开它在那个位置。然后我做了一个左墙开始在相同的大小和位置,然后添加
transform:translate3d(-100px,0px,100px)rotateY(90deg).
然后我做了一个右墙,并添加
transform:translate3d(100px,0px,100px)rotateY(90deg).
这样就正确地创建了房间。但这是在Safari 13版本中。最初我试图先列出旋转步骤,但墙的位置很奇怪。所以我看到了从右到左的行为。

相关问题