2d和3d变换

374 阅读4分钟

transform-origin

transform-origin: x2 y2 z2

  • 默认值:以元素自身的中心位置为变换原点
  • 将当前变换原点(x1,y1,z1) 变为 (x1 + x2,y1 + y2,z1 + z2)
    • % px em
    • 水平方向取值,相对元素的宽,left center bottom
    • 垂直方向取值,相对元素的高,top center bottom
      • 元素左上角为 0% 0%,右下角为 100% 100%

transform

none | rotate | skew | scale | translate | matrix

2D变换

translate()

translate(a,b)

  • translateX(a)
  • translateY(b)
  • 以变换原点为基准,沿x轴方向平移a,沿y方向平移b

rotate()

  • 绕变换原点旋转
    • 注意仅有一个参数

参数:ndeg,n > 0 顺时针,n < 0 逆时针

scale()

  • scalex() + scaley() = scale(x,y)

对元素的坐标轴刻度进行缩放 默认 1 1(水平方向 垂直方向)

  • scale(1,1) scale(2,1)
    • 同一设置了100px * 100px的逻辑像素,转换为物理像素,然后显示到我们的电脑屏幕上,后者的宽比前者大一倍
    • 首先我们假设原来x 坐标轴1刻度可以表示1px(逻辑像素),现在经过scale(2,1)使得坐标轴刻度增大,也就是现在 1刻度可以表示2px(逻辑像素),而scale(2,1)的发挥作用后,该元素从原来 100px * 100px 变换成 200px * 100px,然后再将其转为物理像素,显示在屏幕上
  • 后一个scale以前一个为基础,再对坐标轴刻度缩放
  • 所有缩放过的方向都会保留效果(雁过留声)

transform: scale(2,1) rotate(-45deg) scale(2,1) - 原来的缩放的有效,-45deg旋转后会改变变换原点,这时的缩放也有效

skew

  • 它的坐标轴比较特殊,垂直方向为x轴,水平方向为y轴
  • 倾斜y,保持宽度
  • 倾斜x,保持高度

matrix

参考文章:

  • transform: matrix(a,b,c,d,e,f)
  • 最后一行固定(0,0,1)
  • x, y表示转换元素的所有坐标
  • 变换矩阵 * 坐标矩阵 = 新坐标矩阵
  • transform: matrix(1, 0, 0, 1, 30, 30); === transform: translate(30px, 30px);

3D变换

translate3d()

  • translate3d(a,b,c)
  • translateX(a)
  • translateY(b)
  • translateZ(c)
    • 需要设置perspective才会起作用

rotateX() / rotateY() / rotateZ()

旋转后,变换原点会一起变化(x,y轴也发生变化)

  • 参数:ndeg
  • 绕当前坐标轴旋转,n > 0时的旋转方向如下

rotate3d

transform: rotate3d(x,y,z,angle)

  • 以矢量(x,y,z)为旋转轴,旋转angle
  • angle > 0,顺时针,反之

scale3d

scale() + scalez

  • scale3d(x,y,z)
    • scalez()

matrix3d()

默认值

perspective

Use - 用上透视,更有立体感

  • 舞台元素上的,perspective:npx
    • 给整个舞台设置了一个眼睛,一般舞台元素有很多子元素
  • 当前动画元素上的,transform:perspective(npx)
    • 给该元素设置了眼睛,一般是父容器的包含很多子容器,然后给子容器设置

透视原理

  • Screen可以当作浏览器或屏幕,我们看到的是Screen的像
    • tanslateZ(),可以改变当前元素与Screen的距离
    • perspective:表示眼睛距离屏幕的距离
  • 一开始我们没设置perspective,即none时,正常效果显示
  • 而当我们设置了perspective时,屏幕上的成像是由我们的眼睛发射射线,经过白圈而投影到Screen上的像就是我们所看到的实际效果
    • translateZ:0,有perspective时,白圈和黑圈重合,正常效果
    • translateZ > 0,且有perspective时,眼睛看向黑圈,发射的光线,经过黑圈后,成像在Screen的白圈就是我们看到的实际效果
    • 当有translateZ < 0, 且有perspective时,眼睛看向黑圈,发射的射线,经过Screen形成的白圈就是我们实际看到的效果

perspective-origin

  • 变换眼睛的位置,默认center、center
    • n% ,水平方向的width * n%,垂直方向的height * n%

preserve-3d

transform-style: preserve-3d

  • 一般而言,该声明应用在3D变换的兄弟元素们的父元素上,也就是舞台元素
    • 默认为flat,也就是2D渲染层,指明3D渲染层后,该元素有立体效果

木马旋转

  • 原博文案例复现地址:www.zhangxinxu.com/wordpress/2…

  • 原博文地址:www.zhangxinxu.com/wordpress/2…

  • html结构:舞台包含很多子元素

  • 舞台css,首先加上perspective,使得translateZ可以生效,然后加上transform-style:presever-3d使得舞台变为3d渲染层

  • 子元素css:9张照片平分360deg,然后每张宽度是128px,计算出translateZ应该是多少

  • 正视图看translateZ的肉眼看上去效果不明显

  • 但设置眼睛为50% 100%,用仰视的视角解释translateZ,其实图片是沿着图中所画的Z轴平移我们所设置的像素

  • 完整代码

<div class="stage">
    <img src="../img/mm1.jpg" class="piece" >
    <img src="../img/mm2.jpg" class="piece" >
    <img src="../img/mm3.jpg" class="piece" >
    <img src="../img/mm4.jpg" class="piece" >
    <img src="../img/mm5.jpg" class="piece" >
    <img src="../img/mm6.jpg" class="piece" >
    <img src="../img/mm7.jpg" class="piece">
    <img src="../img/mm8.jpg" class="piece">
    <img src="../img/mm9.jpg" class="piece">
</div>
.stage {
      padding: 50% 50%;
      width: 128px;
      height: 96px;

      margin: 0 auto;
      background-color: #f0f0f0;
      perspective: 800px;
      perspective-origin: 50% 100%;
      transform-style: preserve-3d;

      position: relative;
      top: 0;
    }
    .piece {
      position: absolute;
      width: 128px;
      box-shadow: 0 1px 3px rgba(0,0,0,.5);
    }
.piece:nth-child(1) { 
  transform: rotateY(   0deg ) translateZ(195.839px);
}
.piece:nth-child(2) { 
  transform: rotateY(  40deg ) translateZ(195.839px); 
}
.piece:nth-child(3) { 
  transform: rotateY(  80deg ) translateZ(195.839px); 
}
.piece:nth-child(4) { 
  transform: rotateY( 120deg ) translateZ(195.839px); 
}
.piece:nth-child(5) { 
  transform: rotateY( 160deg ) translateZ(195.839px); 
}
.piece:nth-child(6) { 
  transform: rotateY( 200deg ) translateZ(195.839px); 
}
.piece:nth-child(7) { 
  transform: rotateY( 240deg ) translateZ(195.839px); 
}
.piece:nth-child(8) { 
  transform: rotateY( 280deg ) translateZ(195.839px); 
}
.piece:nth-child(9) { 
  transform: rotateY( 320deg ) translateZ(195.839px); 
}