Skip to content

变形动画

基础知识

CSS 提供的变形动作。

选项说明
none定义不进行转换。
translate(x,y)定义 2D 转换。
translate3d(x,y,z)定义 3D 转换。
translateX(x)定义转换,只是用 X 轴的值。
translateY(y)定义转换,只是用 Y 轴的值。
translateZ(z)定义 3D 转换,只是用 Z 轴的值。
scale(x,y)定义 2D 缩放转换。
scale3d(x,y,z)定义 3D 缩放转换。
scaleX(x)通过设置 X 轴的值来定义缩放转换。
scaleY(y)通过设置 Y 轴的值来定义缩放转换。
scaleZ(z)通过设置 Z 轴的值来定义 3D 缩放转换。
rotate(angle)定义 2D 旋转,在参数中规定角度。
rotate3d(x,y,z,angle)定义 3D 旋转。
rotateX(angle)定义沿着 X 轴的 3D 旋转。
rotateY(angle)定义沿着 Y 轴的 3D 旋转。
rotateZ(angle)定义沿着 Z 轴的 3D 旋转。
skew(x-angle,y-angle)定义沿着 X 和 Y 轴的 2D 倾斜转换。
skewX(angle)定义沿着 X 轴的 2D 倾斜转换。
skewY(angle)定义沿着 Y 轴的 2D 倾斜转换。
perspective(n)为 3D 转换元素定义透视视图。
perspective-origin透视位置

行级元素

行级元素不产生变形效果,将其转为 inline-blockblock 以及弹性元素时都可以产生变化效果。

移动元素

translate

使用 translate 可以控制按 X、Y 同时移动操作,第一个值控制 X 移动,第二个值控制 Y 移动。

元素居中

居中可以使用多种方式,如弹性布局、定位操作,下面来看使用移动操作居中。

css
div{
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

translateZ

控制 Z 轴移动,正数向外、负数向里移动。因为 Z 轴是透视轴没有像 X/Y 一样的固定尺寸,所以不能使用百分数。

缩放元素

scale

使用 scale 可同时设置 X/Y 轴的缩放,如果只设置一个值时表示两轴缩放相同。

使用数值定义缩放,如 .5 表示缩小一半,2 表示放大两倍。

scaleZ

沿 Z 轴缩放元素,需要有 3D 透视才可以查看到效果。

旋转操作

旋转放心遵循左手定则,即大拇指指向坐标轴正向,手握方向为正向,反之为负向。

rotate

在 X 与 Y 轴平面旋转,效果与使用 rotateZ 相同。可以是deg,也可以是turn 1turn=360

rotate3d

同时设置 X/Y/Z 轴的旋转向量值来控制元素的旋转。

需要同时设置如下四个参数

css
rotate3d(tx,ty,tz,angle)

综合案例

html
<style>
    main.love-tranform-clock {
        margin: 50px;
        position: relative;
        width: 400px;
        height: 400px;
        border-radius: 50%;
        background: #34495e;

        &::before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            background: radial-gradient(at right, #27ae60, #e67e22, #e74c3c, #e67e22, #27ae60);
            transform: scale(1.2);
            z-index: -1
        }

        .line {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 100%;
            height: 100%;
            transform: translate(-50%, -50%);
            display: flex;
            justify-content: center;
            align-items: center;

            &::after {
                content: "";
                position: absolute;
                top: 50%;
                left: 50%;
                width: 100%;
                height: 100%;
                border-radius: 50%;
                background: #34495e;
                transform: translate(-50%, -50%) scale(0.85);
            }

            &>div {
                width: 2px;
                height: 20px;
                background-color: #fff;
                position: absolute;
                top: 50%;
                left: 50%;
                width: 10px;
                height: 95%;
                transform: translate(-50%, -50%);

                &:nth-child(1) {
                    transform: translate(-50%, -50%) rotate(30deg);
                }

                &:nth-child(2) {
                    transform: translate(-50%, -50%) rotate(60deg);
                }

                &:nth-child(3) {
                    transform: translate(-50%, -50%) rotate(90deg);
                }

                &:nth-child(4) {
                    transform: translate(-50%, -50%) rotate(120deg);
                }

                &:nth-child(5) {
                    transform: translate(-50%, -50%) rotate(150deg);
                }

                &:nth-child(6) {
                    transform: translate(-50%, -50%) rotate(180deg);
                }

            }
        }

        .hour {
            position: absolute;
            left: 50%;
            bottom: 50%;
            width: 15px;
            height: 25%;
            background-color: #95a5a6;
            transform: translate(-50%, 0);
        }

        .minute {
            position: absolute;
            left: 50%;
            bottom: 50%;
            width: 8px;
            height: 30%;
            background-color: #3498db;
            transform: translate(-50%, 0) rotate(30deg);
            transform-origin: bottom center;
        }


        .second {
            position: absolute;
            left: 50%;
            bottom: 50%;
            width: 4px;
            height: 40%;
            background-color: #c5dd13;
            transform: translate(-50%, 0) rotate(120deg);
            transform-origin: bottom center;
            transition: 10s linear;
        }

        .point {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 20px;
            height: 20px;
            background-color: #f00;
            border-radius: 50%;
            transform: translate(-50%, -50%);
        }

        &:hover .second {
            transform: translate(-50%, 0) rotate(360deg);
        }
    }
</style>
<main class="love-tranform-clock">
    <section class="line">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
    </section>
    <div class="hour"></div>
    <div class="minute"></div>
    <div class="second"></div>
    <div class="point"></div>
</main>

倾斜操作

默认情况下倾斜变形的参考点为图形正中心位置,即矩形中心。

skew

同时设置 X/Y 轴倾斜操作,不指定第二个参数时 Y 轴倾斜为零。

skew(x) = skewX(x)

变形基点

使用 transform-origin 设置元素的 X/Y/Z 操作的基点,用于控制旋转、倾斜等操作。

  • 元素移动不受变形基点所影响
  • 基点是元素原始空间位,而不是 translate 移动后的空间位

元素变形或偏移原点关键字所代表的值,默认的转换原点是 center

keywordvalue
left0%
center50%
right100%
top0%
bottom100%

新年贺卡

源代码
html
   <style>
    .love-transform-card {
      	margin: 120px;
        width: 300px;
        height: 200px;
        background: #e67e22;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 3em;
        color: whitesmoke;
        position: relative;
        transform-style: preserve-3d;
        transform: perspective(600px) rotateX(35deg) rotateY(15deg);

        &::before,
        &::after {
            transition: 1s;
            background: #e74c3c;
            line-height: 4em;
            backface-visibility: visible;
        }

        &::before {
            content: '新年';
            width: 150px;
            height: 100%;
            left: 0px;
            top: 0;
            text-align: right;
            position: absolute;
            transform-origin: left;
        }

        &::after {
            content: '快乐';
            width: 150px;
            height: 100%;
            right: 0px;
            top: 0;
            position: absolute;
            transform-origin: right;
        }

        &:hover::before {
            transform: rotateY(-170deg);
        }

        &:hover::after {
            transform: rotateY(170deg);
        }
    }
</style>

<div class="love-transform-card">I Love You</div>
I Love You

变形顺序的影响

先旋转后移动, 旋转就是参考原来位置的

先移动后旋转, 旋转是参考移动后的位置的

圆圈
html
<style>
  ul.love-transform-circle {
      width: 200px;
      height: 200px;
      background: #ffc00d;
      opacity: 0.5;
      border-radius: 50%;
      position: relative;
      transition: 1s;
        li {
      position: absolute;
      top: 50px;
      left: 50px;
      width: 80px;
      height: 80px;
      background: pink;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      transition: all 0.5s ease-in-out;
      transform-origin: 150px 150px;
      transition: 0.5s;
      opacity: 0;
  }

  &:hover li {
      top: -50px;
      left: -50px;
      opacity: 1;
  }

  &:hover li:nth-child(1) {
      transform: rotate(40deg);
  }

  &:hover li:nth-child(1)>span {
      transform: rotate(1040deg);
  }

  &:hover li:nth-child(2) {
      transform: rotate(80deg);
  }

  &:hover li:nth-child(2)>span {
      transform: rotate(1000deg);
  }

  &:hover li:nth-child(3) {
      transform: rotate(120deg);
  }

  &:hover li:nth-child(3)>span {
      transform: rotate(960deg);
  }

  &:hover li:nth-child(4) {
      transform: rotate(160deg);
  }

  &:hover li:nth-child(4)>span {
      transform: rotate(720deg);
  }

  &:hover li:nth-child(5) {
      transform: rotate(200deg);
  }

  &:hover li:nth-child(5)>span {
      transform: rotate(880deg);
  }

  &:hover li:nth-child(6) {
      transform: rotate(240deg);
  }

  &:hover li:nth-child(6)>span {
      transform: rotate(1680deg);
  }

  &:hover li:nth-child(7) {
      transform: rotate(280deg);
  }

  &:hover li:nth-child(7)>span {
      transform: rotate(1920deg);
  }

  &:hover li:nth-child(8) {
      transform: rotate(320deg);
  }

  &:hover li:nth-child(8)>span {
      transform: rotate(2200deg);
  }

  &:hover li:nth-child(9) {
      transform: rotate(360deg);
  }
    
  &:hover li:nth-child(9)>span {
      transform: rotate(2520deg);
  }
}
</style>
<ul class="love-transform-circle">
  <li><span>1</span></li>
  <li><span>2</span></li>
  <li><span>3</span></li>
  <li><span>4</span></li>
  <li><span>5</span></li>
  <li><span>6</span></li>
  <li><span>7</span></li>
  <li><span>8</span></li>
  <li><span>9</span></li>
</ul>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

透视景深

perspective

  • 使用 perspective 来控制元素的透视景深
  • perspective 规则为舞台元素控制景深,transform的 perspective函数为控制单个元素

舞台透视

perspective 规则用于将父级整个做为透视元素,会造成里面的每个子元素的透视是不一样的。就像现实中摆一排杯子,是使用统一透视的,每个杯子的透视不一样,造成有大有小。

单独透视

perspective 函数用于为元素设置单独透视,下面是为元素单独设置透视参数,每个元素的透视效果是一样的。

正方体
html
  <style>
    main.love-transform-square {
        position: relative;
        left: 50%;
        top: 50%;
        width: 200px;
        height: 200px;
        transform-style: preserve-3d;
        transform-origin: 50% 50% 50px;
        perspective-origin: -500px -500px;
        transform: rotate3d(1, 0.6, 0.7, 50deg);
        transition: 2s;

        &:hover {
            transform: rotate3d(0.4, 0.9, 0.3, 170deg);
        }

        div {
            position: absolute;
            width: 200px;
            height: 200px;
            background: #3498db;
            font-size: 30px;
            color: #fff;
            line-height: 200px;
            opacity: 0.5;
            text-align: center;
            transition: 5s;
        }

        div:nth-child(1) {
            background: peru;
            transform: translateZ(-200px);
        }

        div:nth-child(2) {
            background: pink;
            transform-origin: right;
            transform: rotateY(-90deg);
        }

        div:nth-child(3) {
            background: yellow;
            transform-origin: left;
            transform: rotateY(90deg);

        }

        div:nth-child(4) {
            background: green;
            transform-origin: top;
            transform: rotateX(270deg);
        }

        div:nth-child(5) {
            background: red;
            transform-origin: bottom;
            transform: rotateX(90deg);

        }
    }
</style>
<main class="love-transform-square">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
</main>
1
2
3
4
5
6

隐藏背面

backface-visibility

使用 backface-visibility 用于控制是否可以看到元素的背面。

  • 一般设置在元素上而不是舞台元素上
  • 需要舞台元素(父级元素)设置 transform-style: preserve-3d

过度延迟

transitionend

用于控制过渡结束后执行的 JS 事件,简写属性会触发多次如 border-radius 会触发四次事件,不难理解因为可以为border-bottom-left-radius 等四个属性独立设置过渡,所以就会有四次事件。

属性说明
propertyName结束过渡样式
elapsedTime过渡需要的时间
pseudoElement过渡的伪元素
isTrustedtrue:用户触发,false:脚本触发