# transform 2D 与 3D 转换

TIP

深入浅出 transform 属性,2D、3D 转换,项目中的应用场景和最佳实践

# 一、transform 属性

TIP

  • 在 CSS 中,利用transform这个属性实现对元素进行旋转,缩放,倾斜或平移。
  • transform 属性的值可以是 none 或一个或多个 css 变换函数。
  • transform 的值不是 none 时,元素会创建自己的层叠上下文

# 1、transform 的 2D 变换函数

属性值 描述 实例
translate(x,y) x,y 为长度单位,可以是 px,也可以是百分比%,
x 表示元素在 x 轴上的移动量
y 表示元素在 y 轴上的移动量,如果 y 值不写,则默认为 0,例如 translate(10px)表示 translate(10px,0)
transform:translate(100px,200px)
translateX(x) x 为长度单位,可以是 px,也可以是百分比%
表示元素在平面 x 轴上的位移量
transform:translateX(300px)
translateY(y) y 为长度单位,可以是 px,也可以是百分比%
表示元素在平面 Y 轴上的位移量
transform:translateY(200px)
rotate(ax) ax 代表旋转的角度
正角表示顺时针旋转
负角表示逆时针旋转
transform:rotate(30deg)
scaleX(x) x 数字类型,表示元素在 x 轴上的缩放比 transform:scaleX(2)
scaleY(y) y 数字类型,表示元素在 y 轴上的缩放比 transform:scaleY(2)
scale(x,y) x 数字类型,表示元素在 x 轴上的缩放比
y 数字类型,表示元素在 y 轴上的缩放比
当只有 x,没有 y 时,则 y 默认为 x,元素在 x,y 轴上均匀缩放
transform:scale(2,3)
skew(ax,ay) ax 表示一个角度,表示沿着 x 横坐标扭曲元素的角度
ay 表示一个角度,表示沿着 y 纵坐标扭曲元素的角度
transform:skew(30deg,30deg)
skewX(ax) ax 表示一个角度,表示沿着 x 横坐标扭曲元素的角度,形成水平拉伸效果 transform:skewX(30deg)
skewY(ay) ay 表示一个角度,表示沿着 y 纵坐标扭曲元素的角度,形成垂直拉伸效果 transform:skewY(30deg)

# 2、transform 的 3D 转换属性值

属性值 描述 实例
translateZ(z) x 为 px 长度单位
元素在 3D 空间 z 轴方向上的位移量
transform:translateZ(200px)
translate3d(x,y,z) x,y,z 分别为 px 长度单位
x 表示元素在 x 轴坐标上的位移量
y 表示元素在 y 轴坐标上的位移量
z 表示元素在 z 轴坐标上的位移量,该值不能使用百分比,如果使用会被认为是无效属性
transform:translate3d(50px,30px ,50px)
rotateX(ax) 表示元素绕X轴旋转一定的角度
ax 表示度数,可以为正,也可以为负
transform:rotateX(30deg);
rotateY(ay) 表示元素绕Y轴旋转一定的角度
ay 表示度数,可以为正,也可以为负
transform:rotateY(30deg)
rotateZ(az) 表示元素绕Z轴旋转一定的角度
ax 表示度数,可以为正,也可以为负
transform:rotate(30deg);

# 二、2D 转换

TIP

在学习 2D 转换之前,我们先来了解下 2D 平面。下图这个 x 和 y 轴,就是基于 2D 平面图形。后期的所有 2D 动画特效都是在这个 2D 的平面操作。

注意事项:

  • 元素的左上角坐标为 (0,0)
  • (0,0)坐标的右方,为 x 轴的正方向
  • (0,0)坐标的下方,为 y 轴的正方向。

22image-20211111235301316

# 1、translate 位移

TIP

css 中通过给transform添加translate(x,y)translateX(x)translateY(y)来实现元素的水平或垂直位移。

属性值 描述 举例
translate(x,y) 实现元素水平和垂直位移量 translate(30px,50px)
translateX(x) 实现元素水平位移量 translateX(30px)
translateY(y) 实现元素垂直位移量 translateY(50px)

# 2、translate(x,y)

TIP

  • x 和 y 是长度值 length,可以是 px,也可以是%百分比
  • x 表示元素在 x 轴上的位移量,为正表示向右移动,为负表示向左移动
  • y 表示元素在 y 轴上的位移量,为正表示向下移动,为负表示向上移动
  • 位移和相对定位非常像,位移变形也会 "老家留坑",即会占据原来的位置
  • 同时不会对其它元素造成影响,相当于悬浮在其它元素上面。

x,y 为 px 长度单位

/*
	100px:表示元素水平向右移动100px
	200px: 表示元素垂直向下移动200px
*/
transform: translate(100px, 200px);
<style>
  .box {
    width: 100px;
    height: 100px;
  }
  .box1 {
    background-color: tomato;
    /* 元素水平向右移动50px,向下移动50px */
    transform: translate(50px, 50px);
  }
  .box2 {
    background-color: khaki;
  }
</style>
<body>
  <div class="box box1"></div>
  <div class="box box2"></div>
</body>

image-20220727192746913

(x,y)为%百分比

transform: translate(x%, y%);
  • x 和 y 为%百分比,这个百分比分别是相对元素自身的可视宽和可视高而言。
  • 在标准盒子模型下:
    • 水平位移 =(width + 左右 padding + 左右 border) * x%
    • 垂直位移 =(height + 上下 padding + 上下 border) * y%
<style>
  .box {
    width: 200px;
    height: 100px;
  }
  .box1 {
    padding: 25px;
    border: 25px solid skyblue;
    background-color: tomato;
    /* 
            水平位移=(200+25*2+25*2)*50%=150px
            垂直位移=(100+25*2+25*2)*25%=50px;
        	即:translate(50%,25%)等同于translate(150px,50px)
        */
    transform: translate(50%, 25%);
  }
  .box2 {
    background-color: khaki;
  }
</style>
<body>
  <div class="box box1"></div>
  <div class="box box2"></div>
</body>

image-20220727194128199

y 值不写,默认为 0

/*
	transform:translate(x) 等同于 transform:translate(x,0)
	只有x发生位移,y轴上不发生移动
*/
transform: translate(x);
<style>
  .box {
    width: 100px;
    height: 100px;
  }
  .box1 {
    background-color: tomato;
    /* 
            水平位移=100*50%=50px
            垂直位移=0
        */
    transform: translate(50%);
  }
  .box2 {
    background-color: khaki;
  }
</style>
<body>
  <div class="box box1"></div>
  <div class="box box2"></div>
</body>

image-20220727194946600

# 3、translateX(x) 与 translateY(y)

TIP

  • translateX(x)实现元素在 X 轴的位移量
  • translateY(y)实现元素在 Y 轴的位移量
  • 本质上 translate(x,y) 是 translateX 与 translateY 两者的复合写法
/*
	transform:translate(x) 等同于translateX(x)
*/
transform: translate(x);
  • transform 后面如果跟多个变换函数,则各函数之间用空格隔开。
/*
	transform:translate(x,y) 等同于 transform:translateX(x) translateY(y);
*/
transform: translateX(x) translateY(y);
<style>
  .box {
    width: 100px;
    height: 100px;
  }
  .box1 {
    background-color: tomato;
    /* 
            水平向右移动50px
            垂直向下移动30px 
        */
    transform: translateX(50px) translateY(30px);
  }
  .box2 {
    background-color: khaki;
  }
</style>
<body>
  <div class="box box1"></div>
  <div class="box box2"></div>
</body>

image-20220727200049042

# 4、translate 与绝对定位结合实现元素水平垂直居中

/* 
	先利用绝对定位
    让元素的顶部和左侧分别与父元素垂直和水平中间对齐
	然后再利用translate,让元素向上和向左移动自身宽度的一半
	这样就实现了水平和垂直居中
*/
position: absolute;
top: 50%;
left: 50%;
/* 向左和向上分别移动元素自身宽和高的一半 */
transform: translate(-50%, -50%);
<style>
  .box {
    width: 200px;
    height: 150px;
    background-color: tomato;
    position: relative;
  }
  .item {
    width: 50px;
    height: 50px;
    background-color: khaki;
    /* 以下代码实现元素相对父元素水平垂直居中 */
    position: absolute;
    left: 50%;
    top: 50%;
    /* 水平向左和垂直向上,分别移动自身宽和高的一半 */
    transform: translate(-50%, -50%);
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
</body>

image-20220727201448554

# 5、scale 缩放

TIP

css 中通过给transform添加scale(x,y)scaleX(x)scaleY(y)来实现元素的宽高缩放效果

# 6、scale(x,y)

TIP

  • x,y 都是数字类型,也可以用百分比%表示,分别表示元素的宽和高缩放比
  • 当 x,y 的值 >1 时,表示放大; <1 时,表示缩小; =1 表示不变
  • 当只有 x,没有 y 时,则 y 默认为 x,元素宽高同时均匀缩放
/* 宽放大2倍,高放大3倍 */
transform: scale(2, 3);
/* 宽缩小0,5倍,高放大2倍 */
transform: scale(0, 5, 2);
/* 宽高同时放大2倍 */
transform: scale(2);
<style>
  .box {
    width: 100px;
    height: 100px;
    background-color: khaki;
    margin: 150px;
  }
  .item {
    width: 100px;
    height: 100px;
    background-color: rgb(255, 99, 71, 0.5);
    /* 宽放大2倍,高放大1.5倍 */
    transform: scale(2, 1.5);
    /* 宽高同时放大2倍 */
    transform: scale(2);
    /* 宽缩小一半,高放大2倍 */
    transform: scale(0.5, 2);
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
</body>
scale(2,1.5) scale(2) scale(0.5,2)
image-20220727202902953 image-20220727202809415 image-20220727202727025

百分比% 单位

transform:scale(x%,y%)
  • x%和 y%分别相对于元素的可视宽和可视高而言
  • 在标准盒子模型下
    • 宽缩放后大小 =(width + 左右 padding + 左右 border) * x%;
    • 高缩放后大小 =(height + 上下 padding + 上下 border) * y%
<style>
  .box {
    width: 150px;
    height: 150px;
    /* 背景颜色 黄色 */
    background-color: khaki;
    margin: 150px;
  }
  .item {
    width: 50px;
    height: 50px;
    padding: 25px;
    border: 25px solid rgb(243, 147, 147, 0.9);
    /* 
        	宽放大2倍,高缩小一半 
        	宽缩放后大小=(50+25*2+25*2)*200%=300px
        	高缩放后大小=(50+25*2+25*2)*50%=75px
        */
    transform: scale(200%, 50%);
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
  <div class="h"></div>
</body>
scale(200%,50%) scale(200%)
image-20220727210307283 image-20220727210325284

# 7、scaleX(x) 与 scaleY(y)

TIP

  • scaleX(x) 实现元素的宽缩放效果
  • scaleY(Y) 实现元素高缩放效果
  • 本质上 scale(x,y)是 scaleX(x) 与 scaleY(y)的复合写法
/*
	transform:scale(x,y) 同等于 transform:scaleX(x) scaleY(y);
*/
transform: scaleX(x) scaleY(y);
<style>
  .box {
    width: 100px;
    height: 100px;
    background-color: khaki;
    margin: 150px;
  }
  .item {
    width: 100px;
    height: 100px;
    background-color: rgb(255, 99, 71, 0.5);
    /* 宽放大两倍,高缩小一半 */
    transform: scaleX(2) scaleY(0.5);
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
</body>

image-20220727203524118

# 8、skew 斜切

TIP

  • css 中通过给transform添加skew(ax,ay)skewX(ax)skewY(ay)变换函数来实现元素斜切效果
  • skewX(ax):用于水平拉伸,使元素的每个点在水平方向上扭曲一定角度
  • skewY(ay):用于垂直拉伸,使元素的每个点在垂直方向上扭曲一定角度
  • skew(ax,ay):用于水平和垂直拉伸,使元素在水平和垂直方向上扭曲一定角度
  • ax:表示一个角度,用来表示沿着横坐标扭曲元素的角度
  • ay:表示一个角度,用来表示沿着纵坐标扭曲元素的角度
/* X轴斜切 30deg */
skewX(30deg);
/* Y轴斜切 50deg */
skewY(50deg);
/* X轴斜切 30deg Y轴斜切50deg*/
skew(30deg,50deg)
<style>
  .box {
    width: 100px;
    height: 100px;
    margin: 100px;
    background-color: khaki;
    transform: skewX(30deg);
    /* transform: skewX(-30deg); */
    /* transform: skew(30deg, 30deg); */
  }
</style>
<body>
  <div class="box"></div>
</body>
skewX(30deg) skewX(-30deg) skewY(30deg) skew(30deg,30deg)
image-20220801132019211 image-20220801133048114 image-20220801132220966 image-20220801132342017

# 9、rotate 旋转

TIP

  • css 中通过给transform:rotate(ax)来实现元素旋转效果
  • ax 表示旋转的角度,比如rotate(45deg)
  • ax 为正,表示顺时针方向旋转
  • ax 为负,表示逆时针方向旋转
点击查看完整源代码
<style>
  .body,
  ul {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style-type: none;
  }
  ul li {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 20px;
    float: left;
  }
  .item {
    height: 100%;
    background-color: khaki;
  }
  .item1 {
    /* 顺时针旋转到30deg */
    transform: rotate(30deg);
  }
  .item2 {
    /* 逆时针旋转到30deg */
    transform: rotate(-30deg);
  }
  .item3 {
    /* 顺时针旋转到180deg */
    transform: rotate(180deg);
  }
  .item4 {
    /* 顺时针旋转30deg */
    transform: rotate(450deg);
  }
</style>
<body>
  <ul>
    <li>
      <div class="item item1">30deg</div>
    </li>
    <li>
      <div class="item item2">-30deg</div>
    </li>
    <li>
      <div class="item item3">180deg</div>
    </li>
    <li>
      <div class="item item4">450deg</div>
    </li>
  </ul>
</body>

image-20220727212754232

# 10、transform-origin

TIP

  • transform-origin 属性,设置元素的变换原点,即元素在变换时是以围绕那个点来发生变换的。
  • 默认值:transform-origin:50% 50% 0;
/*
	x: 表示x轴的坐标位置
	y: 表示y轴的坐标位置
	z: 表示z轴的坐标位置
*/
transform-orign: x y z;
  • x , y 的值,可以长度值(px 或百分比%)还可以是预设的关键词
  • z 的值只能是长度值 px

注意事项

  • 在我们没有讲到 3D 之前,我们先只在 2D 的基础上来演示,所以只需要写两个值就 ok,即transform-origin:x y;
  • 在 2D 转换中,元素的默认变换原点为元素的中心 ( transform-origin:50% 50%;)

22image-20211111235301316

# ① 关键字表示

TIP

关键词(left、right)与(top、bottom) 与 center 三组中任意一个与另一组中的一个关键字组合来表示

如下表

关键 字 描述
left 原点为元素左边中间位置,同left center一样
right 原点为元素右边中间位置,同right center一样
top 原点为元素上边中间位置,同top center一样
bottom 原点为元素下边中间位置,同bottom center一样
center 原点为元素中间位置,同center center一样
top left 原点为元素左上角,相当于坐标(0 0)
top right 原点为元素右上角
left bottom 原点为元素左下角
right bottom 原点为元素右下角

元素的默认变换原点为元素的中间位置transform-origin:center;

点击查看完整源代码
<style>
  .body,
  ul {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style-type: none;
    margin: 50px;
  }
  ul li {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 40px;
    float: left;
  }
  .item {
    height: 100%;
    background-color: khaki;
    /* 顺时针旋转60deg */
    transform: rotate(60deg);
  }
  .item1 {
    /* 旋转的原点 */
    transform-origin: top;
  }
  .item2 {
    /* 旋转的原点 */
    transform-origin: right;
  }
  .item3 {
    /* 旋转的原点 */
    transform-origin: bottom;
  }
  .item4 {
    /* 旋转的原点 */
    transform-origin: left;
  }
  .item5 {
    /* 旋转的原点 */
    transform-origin: center;
  }
</style>
<body>
  <ul>
    <li>
      <div class="item item1">top</div>
    </li>
    <li>
      <div class="item item2">right</div>
    </li>
    <li>
      <div class="item item3">bottom</div>
    </li>
    <li>
      <div class="item item4">left</div>
    </li>
    <li>
      <div class="item item5">center</div>
    </li>
  </ul>
</body>

image-20220727222754345

# ② 数值表示法

TIP

transform-origin: x y;
  • x , y 为长度单位(px 或百分比%)
  • 当 y 省略不写时,默认为元素的垂直中心点
/* 变换原点:为左上角 */
transform-origin: 0 0;
/* 变换原点为:x轴20px 与y轴30px相交的位置 */
transform-origin: 20px 50px;
/* 变换原点:为上边的中间点 */
transform-origin: 0;
点击查看完整源代码
<style>
  .body,
  ul {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style-type: none;
    margin: 50px;
  }
  ul li {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 40px;
    float: left;
  }
  .item {
    height: 100%;
    background-color: khaki;
    /* 元素旋转60deg */
    transform: rotate(60deg);
  }
  .item1 {
    /* 旋转的原点 */
    transform-origin: 0 0;
  }
  .item2 {
    /* 旋转的原点 */
    transform-origin: 20px 20px;
  }
  .item3 {
    /* 旋转的原点 */
    transform-origin: 50px 50px;
  }
  .item4 {
    /* 旋转的原点 */
    transform-origin: 100px 0px;
  }
  .item5 {
    /* 旋转的原点 */
    transform-origin: 50px 100px;
  }
</style>
<body>
  <ul>
    <li>
      <div class="item item1">0 0</div>
    </li>
    <li>
      <div class="item item2">20px 20px</div>
    </li>
    <li>
      <div class="item item3">50px 50px</div>
    </li>
    <li>
      <div class="item item4">100px 0px</div>
    </li>
    <li>
      <div class="item item5">50px 100px</div>
    </li>
  </ul>
</body>

image-20220727224023192

# ③ 百分比表示法

TIP

百分比相对的是元素自身的可视宽和可视高而言

点击查看完整源代码
<style>
  .body,
  ul {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style-type: none;
    margin: 50px;
  }
  ul li {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 40px;
    float: left;
  }
  .item {
    width: 100px;
    height: 100px;
    background-color: khaki;
    transform: rotate(60deg);
  }
  .item1 {
    /* 旋转的原点 */
    transform-origin: 100%;
  }
  .item2 {
    /* 旋转的原点 */
    transform-origin: 50%;
  }
  .item3 {
    /* 旋转的原点 */
    transform-origin: 100% 0%;
  }
  .item4 {
    /* 旋转的原点 */
    transform-origin: 100% 100%;
  }
  .item5 {
    /* 旋转的原点 */
    transform-origin: 100% 50%;
  }
</style>
<body>
  <ul>
    <li>
      <div class="item item1">100%</div>
    </li>
    <li>
      <div class="item item2">50%</div>
    </li>
    <li>
      <div class="item item3">100% 0%</div>
    </li>
    <li>
      <div class="item item4">100% 100%</div>
    </li>
    <li>
      <div class="item item5">100% 50%</div>
    </li>
  </ul>
</body>

image-20220727225814240

# ④ scale 与 skew 都可以设置其变换原点

TIP

元素默认的转换原点为元素的中心点 transform-origin:50% 50%;

点击查看完整源代码
<style>
  .box {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 150px;
  }
  .item {
    width: 100px;
    height: 100px;
    background-color: rgb(242, 232, 147, 0.5);
    transform: scale(2);
    /* 原点左上角 */
    transform-origin: 0 0;
    /* 原点右边中间 */
    transform-origin: 100%;
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
</body>
未设置原点 transform-origin:0 0; transform-origin:100%;
image-20220727230638503 image-20220727230621682 image-20220727230554550

# 11、2D 转换综合写法顺序问题

TIP

同时使用多个转换,其多个转换函数之间用空格隔开

transform: translate() rotate() scale();

转换函数的顺序会影响转换的效果,比如:先旋转会影响坐标轴方向

点击查看完整源代码
<style>
  .box {
    width: 100px;
    height: 100px;
    border: 2px solid red;
    margin: 20px 150px;
  }
  .item {
    width: 100px;
    height: 100px;
  }
  .item1 {
    /* 背景颜色为 黄色 */
    background-color: khaki;
    /* 先旋转,再位移 */
    transform: rotate(180deg) translateX(100px);
  }
  .item2 {
    /* 背景颜色为 天蓝色 */
    background-color: skyblue;
    /* 先位移,再旋转 */
    transform: translateX(200px) rotate(180deg);
  }
</style>
<body>
  <div class="box">
    <div class="item item1"></div>
  </div>
  <div class="box">
    <div class="item item2"></div>
  </div>
</body>

image-20220728161529783

注:

当我们需要同时位移和旋转时,需要注意位移和旋转的书写顺序,因为写旋转会影响到元素的坐标轴方向。

# 三、2D 转换实战应用

# 1、旋转的三角形

GIF-2022-7-28-19-58-42

点击查看完整源代码
<style>
  .jiantou::after {
    content: "";
    display: block;
    width: 20px;
    height: 20px;
    border-right: 2px solid red;
    border-bottom: 2px solid red;
    /* 先旋转到-135deg的位置 */
    transform: rotate(-135deg);
    /* 过渡动画 */
    transition: transform 1s;
  }
  .jiantou:hover::after {
    /* 顺时针旋转到45deg */
    transform: rotate(45deg);
  }
</style>
<body>
  <span class="jiantou"></span>
</body>

# 2、鼠标滑动图片放大

GIF-2022-7-28-19-53-26

点击查看完整源代码
<style>
  .item {
    width: 300px;
    height: 300px;
    margin: 50px;
    position: relative;
    overflow: hidden;
  }
  .item::after {
    display: block;
    content: "";
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0);
    /* 绝对定位 */
    position: absolute;
    top: 0;
    left: 0;
    z-index: 3;
  }
  .item .play {
    width: 60px;
    height: 60px;
    background: url(./images/play.png) no-repeat;
    background-size: contain;
    /* 以下4行代码,控制元素水平垂直居中 */
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    /* 透明度为0 */
    opacity: 0;
    transition: all 0.5s;
    z-index: 4;
  }
  .item img {
    transition: transform 1s;
  }
  .item:hover img {
    transform: scale(1.2);
  }
  .item:hover::after {
    background-color: rgba(0, 0, 0, 0.5);
  }
  .item:hover .play {
    opacity: 1;
    /* 这里要特别注意加上 translate(-50% , -50%) */
    transform: translate(-50%, -50%) scale(1.5);
  }
</style>
<body>
  <div class="item">
    <img src="./images/music.jpg" alt="" />
    <span class="play"></span>
  </div>
</body>

# 四、3D 转换

TIP

在学习 3D 转换前,我们先看下下面的 3D 的坐标图,这样会更有利于我们后期对 3D 动画的理解。

在 3D 动画中,元素是围绕 3D 坐标X,Y,Z轴来变换的,我们来看下面这个图

image-20220808225002904

  • 元素的左上角坐标为(0,0,0)
  • x 轴右边为正方向
  • y 轴的下方为正方向
  • z 轴垂直电脑屏幕,射向我们的那一头为正方向

在了解了 3D 坐标后, 我们还需要了解一个非常重要的概念:透视

# 1、perspective 透视

TIP

  • 没有透视定义,不成 3D。
  • 透视是指在平面上描绘物体的空间关系的方法或技术。
  • 要在平面上描绘物体的空间立体感,需要遵顺透视原理中的 近大远小 的规则
  • 当一个物体离我们越近,我们看到他会比离我们远的时候要大。

1541422-20190111170919339-1836249469

视点

  • 你可以理解为我们站在多远的地方来看这个物体,当我们站的越远,我们到的物体就会越小,离得越近看到的就越大。
  • CSS3 中 3D transform 的**透视点 (视点)**是在浏览器的前方!

1609428-20190801220139575-2128845822

perspective 属性

  • 在 css3 中,用perspective属性来设置透视距,即模拟人站在离屏幕多远的地方来看电脑上显示的元素。
  • 比如perspective:800px;意思就是在离屏幕 800px 的地方看到这个元素。
  • 如果元素往Z 轴正方向移动,离我们越近,看到物体就越大,
  • 如果元素往Z 轴负方向移动,离我们越远,看到的物体就越小
  • perspective这个属性要设置在 父元素上面。

# 2、translate 3D 位移

TIP

  • translateX(x) 表示水平方向(x 轴)的位移量,与 2D 位移是一样的效果
  • translateY(y) 表示垂直方向(y 轴)的位移量,与 2D 位移是一样的效果
  • translateZ(z) 表示垂直于电脑屏幕方向(z 轴)的位移量
  • translate3d(x,y,z) 表示元素在 x,y,z 三个坐标上的位移量,用来称动元素在 3D 空间中的位置

# ① translateZ(z)

TIP

我们要能看到 3D 的效果,必需要配合perspective 属性,perspective属性用来定义透视强度。

/* 视距为300px  相当于模拟人站在离电脑屏幕300px的位置看这个元素 */
perspective: 300px;

当 perspective 的值为 300px,则 300px 就会成为当下显示效果的基准。在这个基准下

  • translateZ=0 图形大小正常显示
  • 0< translateZ<300 图形变大
  • translateZ>=300 图片不见,相当于图片在你的后面,你肯定是看不见的了
  • translateZ<0 图形变小
点击查看完整源代码
<style>
  .box {
    width: 150px;
    height: 150px;
    border: 2px solid red;
    float: left;
    margin: 100px 30px;
    /* 设置视距为300px */
    perspective: 300px;
    /* 设置视距为900px */
    /* perspective:900px; */
  }
  .item {
    width: 100%;
    height: 100%;
    background-color: rgb(240, 230, 140, 0.7);
  }
  .item1 {
    transform: translateZ(100px);
  }
  .item2 {
    transform: translateZ(-100px);
  }
  .item3 {
    transform: translateZ(0px);
  }
</style>
<body>
  <div class="box">
    <div class="item item1">translateZ(100px)</div>
  </div>
  <div class="box">
    <div class="item item2">translateZ(-100px)</div>
  </div>
  <div class="box">
    <div class="item item3">translateZ(0px)</div>
  </div>
</body>
perspective:300px;
image-20220801164132422
perspective:900px
image-20220801164217443

注:

  • perspective:300px;时,向前移动100px,离元素还差200px
  • perspective:900px;时,向前移动100px,离元素还差800px
  • perspective:300px时看到的要比perspective:900px时的更大。
  • 其向后移动 100px,则看到的更小,原理类似

# ② translate3d(x,y,z)

TIP

  • 表示元素在 x,y,z 三个坐标上的位移量,用来称动元素在 3D 空间中的位置
  • z 的值不能使用百分比,如果使用会被认为是无效属性
点击查看完整源代码
<style>
  .box {
    width: 150px;
    height: 150px;
    border: 2px solid red;
    float: left;
    margin: 100px 30px;
    /* 视距 */
    perspective: 300px;
  }
  .item {
    width: 100%;
    height: 100%;
    background-color: rgb(240, 230, 140, 0.7);
  }
  .item1 {
    /*  
          	x轴正方向移动20px
          	y轴正方向移动30px
          	z轴正方向移动50px
         */
    transform: translate3d(20px, 30px, 50px);
  }
  .item2 {
    transform: translate3d(20px, 30px, -50px);
  }
  .item3 {
    transform: translate3d(-20px, -30px, -50px);
  }
</style>
<body>
  <div class="box">
    <div class="item item1">translate3d(20px, 30px, 50px)</div>
  </div>
  <div class="box">
    <div class="item item2">translate3d(20px, 30px, -50px)</div>
  </div>
  <div class="box">
    <div class="item item3">translate3d(-20px, -30px, -50px)</div>
  </div>
</body>

image-20220728002401170

# 3、rotate 3D 旋转

TIP

css 中通过给transform添加下以变换函数值来实现 3D 旋转效果

属性值 描述
rotateX(ax) 表示元素绕X轴旋转一定的角度
ax 表示度数,可以为正,也可以为负
rotateY(ay) 表示元素绕Y轴旋转一定的角度
ay 表示度数,可以为正,也可以为负
rotateZ(az) 表示元素绕Z轴旋转一定的角度
ax 表示度数,可以为正,也可以为负

# ① 3D 旋转方向

image-20211111235204058

左手法则

我们并不需要死记的方式来记住不同轴上的正角和负角的旋转方向。我们可以通过左手法则来记忆。

x 轴 y 轴 z 轴
大拇指方向指向 x 的正方向,剩下四个手指的方向为 x 轴旋转的正方向,那反过来就是反方向了 大拇指方向指向 Y 的正方向,剩下四个手指的方向为 Y 轴旋转的正方向,那反过来就是反方向了 大拇指方向指向 Z 的正方向,剩下四个手指的方向为 Z 轴旋转的正方向,那反过来就是反方向了
image-20220727233218168 5e6909fd9c797e6a257d39cabdcabb6

# ② rotateX、rotateY、rotateZ

点击查看完整源代码
<style>
  .box {
    width: 150px;
    height: 150px;
    border: 2px solid red;
    float: left;
    margin: 50px 20px;
    /* 设置3D的透视距,你可以理解为站在多远的地方来看这个物体 */
    perspective: 600px;
  }
  .item {
    width: 150px;
    height: 150px;
    background-color: skyblue;
    font-size: 20px;
  }
  .item1 {
    transform: rotateX(40deg);
  }
  .item2 {
    transform: rotateX(-40deg);
  }
  .item3 {
    transform: rotateY(40deg);
  }
  .item4 {
    transform: rotateY(-40deg);
  }
  .item5 {
    transform: rotateZ(40deg);
  }
  .item6 {
    transform: rotateZ(-40deg);
  }
</style>
<body>
  <div class="box">
    <div class="item item1">rotateX(40deg)</div>
  </div>
  <div class="box">
    <div class="item item2">rotateX(-40deg)</div>
  </div>
  <div class="box">
    <div class="item item3">rotateY(40deg)</div>
  </div>
  <div class="box">
    <div class="item item4">rotateY(-40deg)</div>
  </div>
  <div class="box">
    <div class="item item5">rotateZ(40deg)</div>
  </div>
  <div class="box">
    <div class="item item6">rotateZ(-40deg)</div>
  </div>
</body>

image-20220727235542783

# 4、transform-style

TIP

设置元素的子元素是位于 3D 空间中还是平面中

描述
flat 表示所有子元素在 2D 平面呈现。
preserve-3d 表示所有子元素在 3D 空间中呈现。
点击查看完整源代码
<style>
  .box {
    width: 200px;
    height: 200px;
    border: 2px solid red;
    margin: 20px 150px;
    position: relative;
    /* 视距 */
    perspective: 300px;
    /* 设置元素的子元素是位于 3D 空间中  */
    transform-style: preserve-3d;
  }
  .item {
    width: 200px;
    height: 200px;
    position: absolute;
    left: 0;
    top: 0;
  }
  .item1 {
    background-color: khaki;
    /* x轴正方向顺转60deg */
    transform: rotateX(60deg);
  }
  .item2 {
    background-color: skyblue;
    /* y轴正方向顺转 60deg */
    transform: rotateY(60deg);
  }
</style>
<body>
  <div class="box">
    <div class="item item1"></div>
    <div class="item item2"></div>
  </div>
</body>
transform-style:flat 效果 transform-style:preserve-3d 效果
image-20220728162515025 image-20220728162434982

# 五、2D 与 3D 简单总结

# 1、变换函数

TIP

  • 位移变换函数:translate(x,y)、 translateX(x) 、 translateY(y) 、 translateZ(y)
    • x,y 的值为单位长度,可以是 px、百分比
    • z 的值只能为 px 长度单位。
    • translate(x) 同等于 translate(x,0);
  • 缩放变换函数:scale(x,y) 、scaleX(x)、 scaleY()
    • x,y 的值为数字,分别表示宽度和长度的缩放比例
    • scale(x) 表示 y 的值和 x 一样大,实现等比缩放
  • 斜切变换函数:skew(ax,ay)、 skewX(ax)、 skewY(ax)
    • ax、ay 分表示水平和垂直拉升,使元素与 x 轴和 y 轴发生的扭曲角度
  • 旋转变换函数:rotate(ax) 、rotateX() 、 rotateY()、 rotateZ()
    • rotate 表示 2D 平面旋转,ax 表示旋转度数,为正,表示顺时针旋转,为负,表示逆时针旋转
    • rotateX( ax) 、rotateY(ay )、rotateZ(az )表示 3D 旋转,旋转的方向,可以通过左手法则来记忆。

# 2、重要属性

TIP

  • perspective 视距

    • 用来模拟人站在离电脑屏幕多远的距离来看这个元素。
    • 假设 div 的 width:300px;height:300px;perspective:900px;则表示人站在离屏幕 900px 的位置看现在的 div。看到 div 的大小就是我们设置的 width:300px;和 height:300px;的大小
    • 当 div 的 translateZ=0 时,看到的元素大小就是 width:300px 和 height:300px
    • 当 div 的 0<translateZ<300px 时,看到的元素要比实际大
    • 当 div 的 translateZ<0 时,看到的元素要比实际的小
    • 当 div 的 translateZ>300px 时,则看不到元素,因为元素在我们的后面。
  • transform-style 子元素是否在 3D 空间下呈现

    描述
    flat 表示所有子元素在 2D 平面呈现。
    preserve-3d 表示所有子元素在 3D 空间中呈现。
  • transform-origin:x y z; 设置变换的原点

    • 默认值为 transform-origin:50% 50% 0;
    • x y 的值可以是长度单位 px 和百分比% 或预设的关键字

预设关键字如下:

关键 字 描述
left 原点为元素左边中间位置,同left center一样
right 原点为元素右边中间位置,同right center一样
top 原点为元素上边中间位置,同top center一样
bottom 原点为元素下边中间位置,同bottom center一样
center 原点为元素中间位置,同center center一样
top left 原点为元素左上角,相当于坐标(0 0)
top right 原点为元素右上角
left bottom 原点为元素左下角
right bottom 原点为元素右下角

# 3、注意事项

注:

transform 后面多个变换函数,用空格隔开,多个变换函数顺序不一样,结果会不一样。

比如:先旋转会改变坐标轴的方向

# 六、实战案例

TIP

针对性应用场景训练

# 1、飞行的火箭

GIF-2022-7-28-19-37-02

开发步骤:

  • 第一步:插入火箭图,然后利用自定义动画,实现火箭沿左上角和右下角方向来会移动
  • 第二步:定义一个宽 1px 和高 160px,背景颜色为蓝色的盒子,然后定位到火箭旁边,再旋转一定的角度
  • 第三步:自定义动画,实现线条(气流)从上往下移动(Y 轴移动),然后从透明到不透明再到透明的效果
点击查看完整源代码
<style>
  .huojian {
    width: 300px;
    position: absolute;
    top: 200px;
    left: 300px;
    /* 调用关键帧动画 */
    animation: zd 0.4s linear 0s infinite alternate;
  }
  /* 定义火箭震动关键帧动画 */
  @keyframes zd {
    from {
      transform: translateX(-30px) translateY(-30px);
    }
    to {
      transform: translateX(30px) translateY(30px);
    }
  }
  /* 定义气流 */
  .line {
    width: 1px;
    height: 160px;
    background-color: blue;
    position: absolute;
    opacity: 1;
    transform: rotate(55deg);
  }
  .line1 {
    top: 200px;
    left: 400px;
    /* 调用气流关键帧动画 */
    animation: yd 1s linear 0s infinite;
  }
  .line2 {
    top: 240px;
    left: 450px;
    animation: yd 1s linear 0.4s infinite;
  }
  .line3 {
    top: 290px;
    left: 500px;
    animation: yd 1s linear 0.69s infinite;
  }
  .line4 {
    top: 320px;
    left: 550px;
    animation: yd 1s linear 0.2s infinite;
  }
  /* 定义多关键帧动画 ,移动气流 */
  @keyframes yd {
    0% {
      transform: rotate(55deg) translateY(-200px);
      opacity: 0;
    }
    50% {
      transform: rotate(55deg) translateY(200px);
      opacity: 1;
    }
    100% {
      transform: rotate(55deg) translateY(300px);
      opacity: 0;
    }
  }
</style>
<body>
  <!-- 火箭图 -->
  <img src="./images/huojian.jpeg" alt="" class="huojian" />
  <!-- 气流 -->
  <div class="line line1"></div>
  <div class="line line2"></div>
  <div class="line line3"></div>
  <div class="line line4"></div>
  <!-- 添加音乐 -->
  <audio src="./images/huojian.mp3" autoplay loop></audio>
</body>

# 2、创建 3D 导航

GIF-2022-7-28-19-12-06

开发步骤

  • 第一步:利用 ul 标签来制作简单的导航布局
  • 第二步:在每个 li 中添加一个 div 用来实现旋转效果,后面旋转就是要旋转这个 div
  • 第三步:利用 transform 来调整两个 a 标签的构成的盒子的位置
点击查看完整源代码
<style>
  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    background-color: skyblue;
    padding-left: 100px;
    box-sizing: border-box;
    height: 50px;
  }
  ul li {
    float: left;
    perspective: 300px;
  }
  ul li .box {
    /* border: 2px solid red; */
    height: 50px;
    transition: all 1s;
    transform-style: preserve-3d;
  }
  ul li a {
    display: block;
    padding: 0 20px;
    height: 50px;
    text-decoration: none;
    color: #fff;
    line-height: 50px;
    height: 50px;
  }
  a.front {
    background-color: skyblue;
  }
  a.back {
    background-color: khaki;
    transform-origin: top;
    /* 逆时针旋转90deg*/
    transform: rotateX(-90deg);
  }
  ul li:hover .box {
    transform-origin: 50% 50% -25px;
    transform: rotateX(90deg);
  }
</style>
<body>
  <ul>
    <li>
      <div class="box">
        <a href="" class="front">首页</a>
        <a href="" class="back">首页</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">前端开发</a>
        <a href="" class="back">前端开发</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">架构师</a>
        <a href="" class="back">架构师</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">关于我们</a>
        <a href="" class="back">关于我们</a>
      </div>
    </li>
  </ul>
</body>

# 3、翻书效果

GIF-2022-7-28-19-10-50

TIP

  • 构建.book 盒子,然后在.book 中构建.page,后面在旋转翻页效果时,旋转的就是.page 这个盒子
  • .page 沿着 Y 轴的反方向旋转 180deg 来实现翻页效果,翻页时,把转换原点设置为左边中间位置(transform-origin:left;
  • 在.page 盒子中,构建两个 div,.front 作为一页的正面,.back 作为一页的反面。用绝对定位控制位置
  • 要实现翻转时,能看到一页的背面,则给.back 盒子添加 transform:translateZ(-1),使其与正面拉开一点距离
  • 要使翻转后能看到书的反面是正面朝上的,则需要先把.back 旋转 180deg ,即 transform:rotateY(-180deg)
点击查看完整源代码
<style>
  .book {
    width: 300px;
    height: 400px;
    margin: 150px 0 0 300px;
    /* 透视的视距 */
    perspective: 1000px;
  }
  /* 等下翻页,翻转的就是这个盒子 */
  .page,
  .page2 {
    width: 300px;
    height: 400px;
    /* 定位 */
    position: absolute;
    left: 0;
    top: 0;
    /* 子元素在3D空间中呈现 */
    transform-style: preserve-3d;
    /* 旋转的基点为左边中间 */
    transform-origin: 0 50%;
    /* 过渡动画 */
    transition: all 2s;
  }
  .book:hover .page {
    /* 绕Y轴旋转-180deg */
    transform: rotateY(-180deg);
  }
  .page-item {
    width: 300px;
    height: 400px;
  }
  .front {
    background-color: powderblue;
  }
  .back {
    background-color: tomato;
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: -1;
    /* 延z轴向后移动1像素,然后绕Y轴旋转-180deg */
    transform: translateZ(-1px) rotateY(-180deg);
  }
</style>
<body>
  <div class="book">
    <!-- 每一页分为前和后两部分 -->
    <div class="page" style="z-index: 2">
      <div class="page-item front">
        <img src="images/cover1.jpg" alt="" />
      </div>
      <div class="page-item back">
        <img src="./images/cover2.jpg" alt="" />
      </div>
    </div>
    <div class="page2">
      <img src="./images/front.jpg" alt="" />
    </div>
  </div>
</body>

# 4、创建长方体

image-20220728171339748

开发步骤:

  • 第一步:首先构建一个容器,容器为 3D 空间,同时子元素也在 3D 空间中显示
  • 第二步:在容器中构建 6 个长方形,分别代表正方体的 6 个面
  • 第三步:通过定位把元素叠在一起,然后通过位移,旋转来移动每个面的位置
  • 第四步:给容器设置一个旋转角度,这样看正方体更立体一些
点击查看完整源代码
<style>
  .mybox {
    width: 500px;
    height: 500px;
    /* border: 2px solid red; */
    margin: 100px auto;
    /* 相对定位 */
    position: relative;
    perspective: 900px;
    transform-style: preserve-3d;
    /* transition: all 20s; */
  }
  .mybox {
    transform: rotateX(-20deg) rotateY(-30deg);
  }
  .mybox div {
    /* 绝对定位 */
    position: absolute;
    left: 0p;
    bottom: 0;
  }

  /* 正方体:长400px 高300px 厚 200px */
  .before,
  .after {
    width: 400px;
    height: 300px;
    background-color: rgb(240, 230, 140, 0.5);
  }
  .top,
  .bottom {
    width: 400px;
    height: 200px;
    background-color: rgb(255, 98, 70, 0.5);
  }
  .left,
  .right {
    width: 200px;
    height: 300px;
    background-color: rgb(135, 206, 235, 0.5);
  }

  .after {
    transform: translateZ(-200px);
    background-color: rgba(104, 22, 236, 0.5);
  }
  .top {
    transform-origin: bottom;
    transform: translateY(-300px) rotateX(90deg);
  }
  .bottom {
    transform-origin: top;
    transform: translateY(200px) rotateX(-90deg);
  }
  .left {
    transform-origin: right;
    transform: translateX(-200px) rotateY(-90deg);
  }
  .right {
    transform-origin: left;
    transform: translateX(400px) rotateY(90deg);
  }
</style>
<body>
  <div class="mybox">
    <div class="before">最前面</div>
    <div class="after">最后面</div>
    <div class="top">上面</div>
    <div class="bottom">下面</div>
    <div class="left">左边</div>
    <div class="right">右边</div>
  </div>
</body>

# 七、专项案例训练(作业)

根据课程进度完成以下针对性案例开发,开发过程要求:

  • 利用 PS(Photoshop)与 PxCook 结合,在 PS 中的找到 PxCook-切图面板,选中想要切图的图层 或者 图层组 ,然后点击切图面板上的 标记为切图 按钮 -> 再导出到 PxCook
  • 在 PxCook 中下载对应的切图素材即可获取当前案例中的开发素材
  • 开发过程中所需的尺寸在 PxCook 中量取

以上开发开发流程是用于个人训练从切图、量取尺寸,到具体的开发过程,包括平时自学中如果没有 PSD 源文件时,PxCook 是最佳的个人开发工具。因此现在阶段推荐使用这种方式来练习

在实际企业网页开发中(更多是团队协作开发,流程如下)

  • 设计师设计好 UI 设计稿后 -> 会在 PS 中标记切图 -> 导出至蓝湖(国内企业用的多)中
  • 前端开发人员下载网页开发所需的素材 -> 在蓝湖中量取尺寸 -> 即可开发静态页面

我们把 CSS/CSS3 基础知识全部学习完之后,会有 3 大项目开发(PC 端,响应式,移动端)会按照企业真实团队协作的方式,用 3 个项目来完整的实践。

PSD 的源文件设计稿(联系助理老师获取即可)

  • 具体操作步骤讲解,在钉钉群直播回放视频(第十二课:CSS 盒子模型)中可查阅

切记

学习阶段一定要按照以上的流程学习,提前熟悉工具和整个开发步骤,企业真实项目开发就是这样的流程

# 1、CSS3 动画(鼠标移入文字滑入动画效果)

CSS表格布局

点击查看完整版视频讲解

# 2、CSS3 动画(鼠标悬停缩放动画)

CSS3动画-鼠标悬停缩放动画

点击查看完整版视频讲解

# 3、CSS3 动画(鼠标移入旋转动画)

CSS3动画-鼠标移入旋转动画

点击查看完整版视频讲解

# 4、CSS3 开发 Loading 加载动画

CSS3开发Loading加载动画

点击查看完整版视频讲解

# 5、CSS3 开发吃豆豆动画效果

CSS3开发吃豆豆动画效果

点击查看完整版视频讲解

# 6、鼠标悬停 3D 旋转动画效果

鼠标悬停3D旋转动画效果

点击查看完整版视频讲解

# 7、3D 旋转木马效果

3D旋转木马效果

点击查看完整版视频讲解
上次更新时间: 6/8/2023, 9:23:17 PM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X