# 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 是长度值,单位可以是 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

# 2.1、位移值为%百分比

TIP

位移值单位可以 px ,也可以是%百分比

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

# 2.2、位移的默认值

TIP

transform: translate(x,y) 实现位移时,如果 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)来实现元素的宽高缩放效果

缩放不会对其它元素造成影响,相当于悬浮在其它元素上面

# 5.1、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
宽放大 2 倍,高放大 1.5 倍 宽高同比放大 2 倍 宽缩小到 0.1 倍,高度放大 2 倍

# 5.2、百分比% 单位

TIP

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

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

# 7、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 2D 变形原点

TIP

transform-origin 属性,设置元素的 2D 和 3D 变换原点,即元素在变换时是以围绕那个点来发生变换的。

/*
x: 表示x轴的坐标位置
y: 表示y轴的坐标位置
z: 表示z轴的坐标位置
*/
transform-orign: x y z;

注:

  • x , y 的值,可以长度值(px 或百分比%)还可以是预设的关键词
  • z 的值只能是长度值(后面 3d 详细讲)

2D 变形原点

在没有讲到 3D 之前,我们先只在 2D 的基础上来演示,所以只需要写两个值就 ok,即transform-origin:x y;

/*
x: 表示x轴的坐标位置
y: 表示y轴的坐标位置
z: 在没有写的时候,z表示0 
*/
transform-orign: x y;
  • 在 2D 转换中,元素的默认变换原点为元素的中心
transform-origin: 50% 50%; /* 应用于 2D 变换的原点 */

transform-origin

# 10.1、关键字表示

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

# 10.2、 数值表示法

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

# 10.3、百分比表示法

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

# 11、 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-20250104161644836 image-20250104161835184 image-20250104161906954
x 正轴向右,y 正轴向下 先旋转,改变了 x 轴和 y 轴方方向,
x 正轴向左,y 正轴向上。然后再向 x 正轴(左)位移 200px
先向 x 轴正方向(右)位移 200px,再旋转

注:

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

# 12、transform 属性注意事项

TIP

在前面 transform 中定义的转换,在后续的效果中也要带上,否则会出现不按预期效果显示。

<style>
  .box {
    width: 100px;
    height: 100px;
    margin: 50px;
    background-color: skyblue;
    transform: rotate(45deg);
  }
  .box:hover {
    /* 
        我们本想在鼠标移入时,元素可以放大1.2倍。
        但实际效果是,元素确实放大了1.2倍,但元素的旋转效果没有了。
        */
    transform: scale(1.2);
    /* 上面代码等同于 */
    /* transform: rotate(0deg) scale(1.2); */
  }
</style>

<div class="box"></div>

渲染效果:

GIF2025-1-423-52-41

# 常见的错误写法

<style>
  .box {
    width: 200px;
    height: 200px;
    margin: 50px;
    background-color: skyblue;
    position: relative;
  }
  .item {
    width: 100px;
    height: 100px;
    background-color: tomato;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .box:hover .item {
    /* 只有缩放,没有位移*/
    transform: scale(0.5);
    /* 上面代码等价于 transform: translate(0,0) scale(0.5) */
    /* 先缩小再位移 */
    transform: scale(0.5) translate(-50%, -50%);
    /* 先位移 再缩小 */
    /* transform: translate(-50%, -50%) scale(0.5); */
  }
</style>
<div class="box">
  <div class="item"></div>
</div>

鼠标未移入时效果

image-20250106000853521

上面代码 .box:hover .item 选择器中,不同代码,鼠标移入后效果

transform: scale(0.5); transform: scale(0.5) translate(-50%, -50%); transform: translate(-50%, -50%) scale(0.5);
image-20250106000606952 image-20250106000708985 image-20250106000735066
只有缩小,前面的位移丢掉了 先缩小,后面位移是相对缩小后的宽高而言 先位移,水平垂直居中,再缩小

# 三、2D 转换实战应用

TIP

深入浅出,2D 转换 在企业项目中的实战应用。

# 1、旋转的三角形

GIF2025-1-417-19-54

点击查看完整源代码
<style>
  .arrow {
    padding: 10px;
    width: 15px;
    height: 15px;
    border: 1px solid #ddd;
    margin: 20px;
  }
  /* 箭头样式 */
  .arrow::after {
    content: "";
    display: block;
    width: 15px;
    height: 15px;
    border-left: 1px solid #ddd;
    border-top: 1px solid #ddd;
    /* 过渡动画 */
    transition: transform 1s;
  }

  /* 位移+旋转,实现向上箭头 */
  .arrow-up::after {
    transform: translateY(25%) rotate(45deg);
  }
  /* 位移+旋转,实现向下箭头 */
  .arrow-down::after {
    transform: translateY(-25%) rotate(-135deg);
  }
  /* 鼠标移入,向上箭头变向下箭头 */
  .arrow-up:hover::after {
    transform: translateY(-25%) rotate(-135deg);
  }
  /* 鼠标移入,向下箭头变向上箭头 */
  .arrow-down:hover::after {
    transform: translateY(25%) rotate(45deg);
  }
</style>
<body>
  <div class="arrow arrow-up"></div>
  <div class="arrow arrow-down"></div>
</body>

# 2、鼠标滑动图片放大

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

点击查看完整源代码
<style>
  .box {
    width: 300px;
    height: 300px;
    /* border: 1px solid red; */
    margin: 100px;
    position: relative;
    overflow: hidden;
  }
  /* 黑色半透明遮罩层 */
  .box::before {
    content: "";
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0);
    z-index: 2;
    transition: background-color 0.5s;
  }
  .box .img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s;
  }
  .box .play {
    width: 60px;
    height: 60px;
    /* border: 1px solid red; */
    /* 以下4行代码,控制元素水平垂直居中 */
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background: url("./images/play.png") no-repeat center;
    /* background-size: 60px 60px; */
    background-size: contain; /* 填充整个盒子 */
    opacity: 0;
    transition: transform 0.5s, opacity 0.5s;
    z-index: 3;
  }
  /* 鼠标移入,图片放大 */
  .box:hover .img {
    /* transform-origin: 50% 50%; */
    transform: scale(1.2);
  }
  /* 鼠标放上去,播放按扭动画 */
  .box:hover .play {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.2);
  }
  .box:hover::before {
    background-color: rgba(0, 0, 0, 0.5);
  }
</style>

<div class="box">
  <!-- ::before -->
  <img src="./images/music.jpg" class="img" />
  <div class="play"></div>
</div>

# 3、渐进式淡入动画

GIF2025-1-50-35-02

<style>
  body,
  ul,
  li {
    margin: 0;
    padding: 0;
  }
  li {
    list-style: none;
  }
  .imglist {
    width: 1100px;
    height: 250px;
    background-color: #000;
    margin: 50px auto;
    padding: 20px 10px;
    overflow: hidden;
  }
  .imglist li {
    width: 200px;
    height: 250px;
    float: left;
    margin: 0 10px;
  }
  .imglist li img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* 等比缩放,正好覆盖容器 */
  }

  /* 定义延迟加载动画 */
  .animation-fadeIn {
    opacity: 0; /* 透明度为0 */
    transform: translateY(calc(100% + 40px));
    /* 动画名  动画时间  延迟时间  动画结束后如何将样式应用于目标元素(停留在最后一帧)*/
    animation: fadeIn 1s var(--delay) forwards;
  }

  @keyframes fadeIn {
    100% {
      opacity: 1; /* 透明度为1 */
      transform: translateY(0);
    }
  }
</style>

<ul class="imglist">
  <!-- 自动定属性,定义动画执行的延迟时间 -->
  <li class="animation-fadeIn" style="--delay: 0.1s">
    <img src="./images/01.jpg" />
  </li>
  <li class="animation-fadeIn" style="--delay: 0.2s">
    <img src="./images/02.jpg" />
  </li>
  <li class="animation-fadeIn" style="--delay: 0.3s">
    <img src="./images/03.jpg" />
  </li>
  <li class="animation-fadeIn" style="--delay: 0.4s">
    <img src="./images/04.jpg" />
  </li>
  <li class="animation-fadeIn" style="--delay: 0.5s">
    <img src="./images/05.jpg" />
  </li>
</ul>

# 四、3D 转换

TIP

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

在 3D 动画中,元素是围绕 3D 坐标X,Y,Z轴来变换的。

我们来看下面这个图

image-20220808225002904

注:

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

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

# 1、perspective 透视

TIP

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

image-20250104191913576

视点

  • 视点是绘画者(或观察者)眼睛的位置
  • CSS3 中 3D transform 的 透视点(视点) 是在浏览器的前方!

image-20250104190718054

注:

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

1609428-20190801220139575-2128845822

# 2、translate 3D 位移

TIP

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

# 2.1、translateZ(z)

TIP

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

/* 视距为300px  相当于模拟人站在离电脑屏幕300px的位置看这个元素 */
perspective: 300px;
/* 当值为 0 或负值时,无透视变换 */

注:

当 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;
    /* perspective这个属性要设置在3D元素的父元素上面*/
    /* 设置视距为300px  */
    perspective: 300px;
  }
  .box .item {
    width: 100%;
    height: 100%;
    background-color: rgb(240, 230, 140, 0.7);
  }

  .z0 {
    /* 相当于元素在z轴 没有移动 */
    transform: translateZ(0px);
  }
  .z100 {
    /* 元素向Z轴正方向移动 100px  */
    transform: translateZ(100px);
  }
  .z-100 {
    /* 元素向Z轴负方向移动 100px  */
    transform: translateZ(-100px);
  }
</style>

<body>
  <div class="box">
    <div class="item z0">translateZ(0px)</div>
  </div>
  <div class="box">
    <div class="item z100">translateZ(100px)</div>
  </div>
  <div class="box">
    <div class="item z-100">translateZ(-100px)</div>
  </div>
</body>
perspective:300px;
image-20250105115426848
perspective:900px
image-20250105115618317

注:

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

# 2.2、 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;
    /* 设置视距为300px */
    perspective: 300px;
    /* perspective: 900px; */
  }
  .box .item {
    width: 100%;
    height: 100%;
    background-color: rgb(240, 230, 140, 0.7);
  }
  .tz20x30y50 {
    /*  
        x轴正方向移动20px
        y轴正方向移动30px
        z轴正方向移动50px
        */
    transform: translate3d(20px, 30px, 50px);
  }
  .tz20x30y-50 {
    /*  
        x轴正方向移动20px
        y轴正方向移动30px
        z轴负方向移动50px
        */
    transform: translate3d(20px, 30px, -50px);
  }
  .tz-20x-30y-50 {
    transform: translate3d(-20px, -30px, -50px);
  }
</style>

<body>
  <div class="box">
    <div class="item tz20x30y50">translate3d(20px, 30px, 50px)</div>
  </div>
  <div class="box">
    <div class="item tz20x30y-50">translate3d(20px, 30px, -50px)</div>
  </div>
  <div class="box">
    <div class="item tz-20x-30y-50">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 表示度数,可以为正,也可以为负

# 3.1、3D 旋转方向

image-20211111235204058

左手法则

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

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

# 3.2、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;
  }
  .rotateX40deg {
    transform: rotateX(40deg);
  }
  .rotateX-40deg {
    transform: rotateX(-40deg);
  }

  .rotateY40deg {
    transform: rotateY(40deg);
  }
  .rotateY-40deg {
    transform: rotateY(-40deg);
  }
  .rotateZ40deg {
    transform: rotateZ(40deg);
  }
  .rotateZ-40deg {
    transform: rotateZ(-40deg);
  }
</style>

<div class="box">
  <div class="item rotateX40deg">rotateX(40deg)</div>
</div>
<div class="box">
  <div class="item rotateX-40deg">rotateX(-40deg)</div>
</div>
<div class="box">
  <div class="item rotateY40deg">rotateY(40deg)</div>
</div>
<div class="box">
  <div class="item rotateY-40deg">rotateY(-40deg)</div>
</div>
<div class="box">
  <div class="item rotateZ40deg">rotateZ(40deg)</div>
</div>
<div class="box">
  <div class="item rotateZ-40deg">rotateZ(-40deg)</div>
</div>

image-20220727235542783

# 4、transform-style

TIP

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

描述
flat 表示所有子元素在 2D 平面呈现。
preserve-3d 表示所有子元素在 3D 空间中呈现。
点击查看完整源代码
<style>
  .box {
    width: 200px;
    height: 200px;
    border: 2px solid red;
    margin: 150px 150px;
    position: relative;
    /* 视距 */
    perspective: 300px;
    /* 设置元素的子元素是位于 3D 空间中  */
    /* transform-style: preserve-3d; */
  }

  .item {
    width: 200px;
    height: 200px;
    /* 定位元素 */
    position: absolute;
    left: 0;
    top: 0;
  }

  .flat {
    /* 设置元素的子元素是位于 2D 空间中  */
    transform-style: flat;
  }
  .preserve-3d {
    /* 设置元素的子元素是位于 3D 空间中  */
    transform-style: preserve-3d;
  }

  .rotatex60deg {
    background-color: khaki;
    /* x轴正方向顺转60deg */
    transform: rotateX(60deg);
  }
  .rotatey60deg {
    background-color: skyblue;
    /* y轴正方向顺转 60deg */
    transform: rotateY(60deg);
  }
</style>

<!-- 子元素位于 2D 平面中 -->
<div class="box flat">
  <div class="item rotatex60deg"></div>
  <div class="item rotatey60deg"></div>
</div>
<!-- 子元素位于 3D 平面中 -->
<div class="box preserve-3d">
  <div class="item rotatex60deg"></div>
  <div class="item rotatey60deg"></div>
</div>
transform-style:flat 效果 transform-style:preserve-3d 效果
image-20220728162515025 image-20220728162434982

# 5、transform-origin

TIP

transform-origin 属性,设置元素的变换原点,即元素在变换时是以围绕那个点来发生变换的。

/*
x: 表示x轴的坐标位置
y: 表示y轴的坐标位置
z: 表示z轴的坐标位置
*/
/* 前两个值的用法和 2D 变换原点的用法一样 */
transform-orign: x y z;

/*  如果只设置了x, y 坐标,则z的默认值为 0*/
transform-orign: x y;
  • x , y 的值,可以长度值(px 或百分比%)还可以是预设的关键词。
  • z 的值只能是长度值 px

transform-origin 默认值为:

transform-origin: 50% 50% 0px;
  • 50% 50%:这表示变换原点在元素的水平和垂直方向上的中心位置。也就是说,如果不对 transform-origin 进行任何设置,元素的变换(如旋转、缩放等)将以其中心点为基准进行。

  • 0:这表示变换原点在 Z 轴(深度轴)上的位置为 0,即原点位于 2D 平面上,而不是在 3D 空间中偏移。

transform-origin22

关于 3D 变换原点设置后对应的效果演示,在下面实战案例《创建长方体》中演示

# 6、perspective 透视对子元素影响

TIP

在所有子元素 li的父元素 ul 中设置视距 perspective:300px

<style>
  body,
  ul,
  li {
    margin: 0;
    padding: 0;
  }
  .container {
    width: 1200px;
    margin: 50px auto;
  }
  ul {
    list-style-type: none;
    perspective: 300px; /* 视距 - 对所有子元素的影响是不一样的 */
  }
  ul li {
    width: 200px;
    height: 250px;
    float: left;
    /* 对 li 进行旋转 */
    transform: rotateY(10deg);
  }
  /* 选择奇数项 */
  ul li:nth-child(odd) {
    background-color: skyblue;
  }
  /* 选择偶数项 */
  ul li:nth-child(even) {
    background-color: khaki;
  }
</style>

<div class="container">
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

在视觉上,子元素从左往右越来越小,两者间的间距也越来越大

image-20250106184639065

为了让同一父级的所有子元素从左往右倾斜的角度和大小在视觉上呈现一致。我们需要将 perspective:300px 添加到这些子元素上。

  • 我们将perspective:300px 添加到每个 li 元素身上
  • li 中创建子元素 div ,然后对该 div 元素做旋转。
<style>
  body,
  ul,
  li {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style-type: none;
  }
  .container {
    width: 1200px;
    margin: 50px auto;
  }
  ul li {
    width: 200px;
    height: 250px;
    perspective: 300px; /* 视距 - 会创建自己的层叠上下文 */
    float: left;
    position: relative; /* 添加相对定位,后面通过 z-index 提升层级*/
  }
  ul li div {
    width: 200px;
    height: 250px;
    transform: rotateY(20deg); /* 旋转 */
    transition: transform 0.5s; /* 添加过渡动画 */
  }
  /* 选择奇数项 */
  ul li:nth-child(odd) div {
    background-color: skyblue;
  }
  /* 选择偶数项 */
  ul li:nth-child(even) div {
    background-color: khaki;
  }

  ul li:hover {
    z-index: 999; /* 提升层级 */
  }
  /* 让元素不再旋转 然后放大1.2倍 */
  ul li:hover div {
    transform: rotateY(0deg) scale(1.2);
  }
</style>

<body>
  <div class="container">
    <ul>
      <li><div></div></li>
      <li><div></div></li>
      <li><div></div></li>
      <li><div></div></li>
      <li><div></div></li>
      <li><div></div></li>
    </ul>
  </div>
</body>

GIF2025-1-619-09-02

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

TIP

深入浅出 CSS3 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:300pxheight: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;
    left: 300px;
    top: 200px;
  }

  /* 调用震动动画 */
  .animation-vibrate {
    animation: vibrate 1s linear 0s infinite alternate;
  }
  /* 定义震动动画 */
  @keyframes vibrate {
    0% {
      transform: translate(-30px, -30px);
    }
    100% {
      transform: translate(30px, 30px);
    }
  }

  .line {
    width: 1px;
    height: 160px;
    background-color: blue;
    position: absolute;
    /* animation: move 1s linear var(--delay) infinite backwards; */
  }
  .pos1 {
    top: 200px;
    left: 400px;
    /* animation: move 1s linear var(--delay) infinite  backwards; */
  }
  .pos2 {
    top: 240px;
    left: 450px;
    /* animation: move 1s linear var(--delay) infinite backwards ; */
  }
  .pos3 {
    top: 290px;
    left: 500px;
    /* animation-fill-mode: backwards; */
    /* animation: move 1s linear var(--delay) infinite backwards; */
  }
  .pos4 {
    top: 320px;
    left: 550px;
    /* animation: move 1s linear var(--delay) infinite backwards; */
  }

  /* 倾斜从上往下移入再移出动画 */
  .animation-move {
    animation: move 1s linear var(--delay) infinite backwards;
  }

  @keyframes move {
    0% {
      opacity: 0;
      transform: rotate(55deg) translateY(-200px);
    }
    100% {
      opacity: 1;
      transform: rotate(55deg) translateY(200px);
    }
  }
</style>

<body>
  <!-- 火箭图 -->
  <img src="./images/huojian.jpeg" class="huojian animation-vibrate" />
  <!-- 气流 -->
  <div class="line pos1 animation-move" style="--delay: 0s"></div>
  <div class="line pos2 animation-move" style="--delay: 0.4s"></div>
  <div class="line pos3 animation-move" style="--delay: 0.6s"></div>
  <div class="line pos4 animation-move" style="--delay: 0.2s"></div>
  <!-- 添加音乐 现代浏览器不支持音频自动播放,所以音频没有效果
处理方式
用户进入界面前,让他点击开始按扭,播放音乐,看到游戏画面(需要结合JS实现)
因为不支持自动播放音乐--所以课上没讲
-->
  <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>
  body,
  ul,
  li {
    margin: 0;
    padding: 0;
  }
  a {
    text-decoration: none;
  }
  li {
    list-style: none;
  }
  ul li {
    float: left;
    /* 视距 站在多元的地方来看里面的3D动画*/
    perspective: 300px;
    /* border: 1px solid red; */
  }
  ul {
    height: 50px;
    background-color: skyblue;
  }
  ul li .box {
    height: 50px;
    /* 创建一个 3D的空间的 */
    transform-style: preserve-3d;
    transition: transform 0.4s;
    /* 设置旋转的中心点 */
    transform-origin: 50% 50% -25px;
  }
  ul li .box a {
    display: block;
    height: 50px;
    line-height: 50px;
    color: #fff;
    padding: 0px 20px;
  }
  ul li .box a.front {
    background-color: skyblue;
  }
  ul li .box a.bottom {
    background-color: khaki;
    /* 设置旋转的中心点为 顶部的中间 */
    transform-origin: top center;
    /* X 轴负方向旋转90deg  */
    transform: rotateX(-90deg);
  }
  ul li:hover .box {
    /* X 轴正方向旋转90deg  */
    transform: rotateX(90deg);
  }
</style>
<body>
  <ul>
    <li>
      <div class="box">
        <a href="" class="front">首页</a>
        <a href="" class="bottom">首页</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">前端开发</a>
        <a href="" class="bottom">前端开发</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">架构师</a>
        <a href="" class="bottom">架构师</a>
      </div>
    </li>
    <li>
      <div class="box">
        <a href="" class="front">关于我们</a>
        <a href="" class="bottom">关于我们</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 {
    width: 300px;
    height: 400px;
    /* 定位 */
    position: absolute;
    left: 0;
    top: 0;
    /* 子元素在3D空间中呈现 */
    transform-style: preserve-3d;
    /* 旋转的基点为左边中间 */
    transform-origin: 0 50%;
    /* 过渡动画 */
    transition: all 2s;
  }
  /* 每页宽和高 */
  .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);
  }

  /* 鼠标滑到书上,让第一页沿着Y轴旋转-180deg*/
  .book:hover .first {
    /* 绕Y轴旋转-180deg */
    transform: rotateY(-180deg);
  }
</style>
<body>
  <div class="book">
    <!-- 每一页分为前(正面)和 后(反面)两部分 -->
    <div class="page first" 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="page">
      <img src="./images/front.jpg" alt="" />
    </div>
    <!-- 这个效果,不显示底页正面,所以不用绘制 -->
  </div>
</body>

# 4、创建长方体

GIF2025-1-721-50-25

image-20250107204733741

开发步骤:

  • 第一步:首先创建一个名为 .container 的容器,用来放立方体。我们站在离这个容器 900px 的地方,来观察里面的立方体。所以设置perspective: 900px;
  • 第二步:创建一个名为 .mybox 的容器,用来构建立方体。所以需要设置 transform-style: preserve-3d;,将子元素在 3D 空间展示
  • 第三步:在容器中构建 6 个长方形,分别代表正方体的 6 个面
  • 第四步:通过定位把元素叠在一起,然后通过位移,旋转来移动每个面的位置
  • 第五步:给容器设置一个旋转角度,这样看正方体更立体一些
点击查看完整源代码
<style>
  .container {
    /* width: 800px;
        height: 800px; */
    margin: 100px auto;
    /* border: 2px solid red; */
    perspective: 1000px; /* 视距 - 站在离屏幕 1000px的位置来看里面的立方体*/
  }

  .container:hover .mybox {
    transition: transform 10s linear;
    /*  transform-origin: 50% 50% -100px; 旋转的中心点 */
    transform: rotateX(-180deg);
  }

  /* 创建的立方体盒子 长 400px   高 300px   厚 200px */
  .mybox {
    width: 400px;
    height: 300px;
    transform-origin: 50% 50% -100px; /* 旋转的中心点 */
    /* border: 2px solid blue; */
    margin: 150px auto;
    position: relative; /* 相对定位*/
    transform-style: preserve-3d;
    /* animation: rotate 10s linear infinite; */
  }

  /* @keyframes rotate {
    0% {
    transform: rotateX(0deg) rotateY(0deg);
    }
    100% {
    transform: rotateX(-360deg) rotateY(-360deg);
    }
    } */

  .mybox .face {
    position: absolute;
    top: 0;
    left: 0;
  }

  /* 前面和后面 */
  .mybox .before,
  .mybox .after {
    width: 400px;
    height: 300px;
  }
  .mybox .before {
    background-color: rgb(139, 45, 226, 0.5);
  }
  .mybox .after {
    background-color: rgb(125, 248, 1, 0.5);
  }

  /* 上面和下面 */
  .mybox .top,
  .mybox .bottom {
    width: 400px;
    height: 200px;
  }
  .mybox .top {
    background-color: rgb(130, 200, 228, 0.5);
  }
  .mybox .bottom {
    background-color: rgb(253, 99, 72, 0.5);
  }

  /* 左边和右边 */
  .mybox .left,
  .mybox .right {
    width: 200px;
    height: 300px;
  }
  .mybox .left {
    background-color: rgb(241, 224, 71, 0.5);
  }
  .mybox .right {
    background-color: rgb(4, 4, 245, 0.5);
  }

  /* 制后面这个面*/
  .mybox .after {
    transform: translateZ(-200px);
  }
  /* 制作顶部的面 */
  .mybox .top {
    transform-origin: bottom;
    /* 位移 */
    transform: translateY(-100%) rotateX(90deg);
  }
  /* 制作下面的面 */
  .mybox .bottom {
    transform-origin: top;
    transform: translateY(300px) rotateX(-90deg);
  }
  /* 制作左边的面 */
  .mybox .left {
    transform-origin: right;
    transform: translateX(-100%) rotateY(-90deg);
  }

  /* 制作右边的面 */
  .mybox .right {
    transform-origin: left;
    transform: translateX(400px) rotateY(90deg);
  }
</style>

<!-- 用来方立方体的容器 -->
<div class="container">
  <!-- 创建立方体的盒子 -->
  <div class="mybox">
    <div class="face before">最前面</div>
    <div class="face after">最后面</div>
    <div class="face top">top-上面</div>
    <div class="face bottom">bottom - 下面</div>
    <div class="face left">左边</div>
    <div class="face right">右边</div>
  </div>
</div>

# 4.1、改变 transform-origin 变换原点

TIP

可以将上面的对应 css 修改如下,演示 transform-origin 变换原点时,不同的旋转效果

.mybox {
  /* transform: rotateX(-20deg) rotateY(-30deg); */
  /* 将上面代码注释,修改成如下 */
  transform: rotateY(0deg);
  /* 可以修改下面变换原点的值,来看不同的旋转效果 */
  transform-origin: 0% 0% -100px;
  /* transform-origin: 0% 0% 0px; */
  transform-origin: 50% 50% -100px;
}

/* 鼠标移入时,旋转立方体 */
.mybox:hover {
  /*  transform: rotateX(0deg) rotateY(-360deg); */
  /* 将上面代码注释,修改成如下 */
  transform: rotateY(-360deg);
}

变换原点为:transform-origin: 0% 0% 0px 时效果

GIF2025-1-517-52-14

变换原点为:transform-origin: 50% 50% -100px 时效果

GIF2025-1-517-54-24

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

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

  • 利用 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旋转木马效果

点击查看完整版视频讲解
上次更新时间: 1/10/2025, 1:46:33 AM

大厂最新技术学习分享群

大厂最新技术学习分享群

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

X