css3 动画的实现


前言

css3 动画的实现的方案,大概有以下方案:

  • js 的 animation() 方法实现动画(这是一个实验功能,此功能某些浏览器尚在开发中。详见这里)。
  • @keyframes + animation:这是一个实现动画的组合,必须一起使用。
  • transition:表示过渡。transition 可以单独使用,
  • transform:表示变形。使用 transform 实现动画时有两种选择:
    • transform + transition:一次性动画。transform 定义行为,transition 驱动,但一次仅能驱动一次。
    • transform + @keyframes + animation:支持循环动画。在 @keyframes 里使用 transform 定义行为,animation 驱动,可充分调整动画的实现,包括:指定动画任意的执行次数,指定动画的结束与开始的状态等等。

transition 和 animation 实现动画的区别

  • transition:需要触发一个事件才执行动画。
  • animation:自动执行动画,可循环执行。

一、@keyframes + animation

CSS animation 属性

1、@keyframes——创建动画

@keyframes 用来创建动画。其内部规定一个动画——从目前的样式更改为新的样式。

(1)、在 @keyframes 中用 from 和 to 创建动画

@keyframes myfirst{
    from {background: red;}
    to {background: yellow;}
}
/* Safari 与 Chrome */
@-webkit-keyframes myfirst{
    from {background: red;}
    to {background: yellow;}
}

(2)、在 @keyframes 中用 “百分比” 创建动画

// 当动画为 25% 及 50% 时改变背景色,然后当动画 100% 完成时再次改变:
@keyframes myfirst
{
    0%   {background: red;}
    25%  {background: yellow;}
    50%  {background: blue;}
    100% {background: green;}
}
 
@-webkit-keyframes myfirst /* Safari 与 Chrome */
{
    0%   {background: red;}
    25%  {background: yellow;}
    50%  {background: blue;}
    100% {background: green;}
}

(3)、将 @keyframes 嵌套进要添加动画的元素的样式里

将 @keyframes 嵌套进要添加动画的元素的样式里,然后,通过 animation 执行这个动画:

.action-move {
    animation: box-move 3s ease-out;
    -webkit-animation: activity-move 3s ease-out;
    animation-fill-mode: forwards;
    @keyframes box-move {
        0% {transform: scale(1); opacity: 1}
        20% {transform: scale(1.3); opacity: 1}
        40% {transform: scale(1.3); opacity: 1}
        60% {transform: scale(1); opacity: 1}
        80% {transform: scale(1.2); opacity: 1}
        100% {transform: scale(1); opacity: 0}
    }
}

2、animation 执行动画

在 @keyframes 创建动画后,必须通过 animation 属性把该 keyframes 绑定到指定的选择器上,否则动画不会有任何效果。

语法:

{animation: name duration timing-function delay iteration-count direction 
fill-mode play-state;}

animation 属性是以下属性的简写形式:

  • animation-name:必须的。规定 @keyframes 动画的名称。
  • animation-duration:必须的。指定一个动画周期的时长。默认是 0s,表示无动画。
  • animation-timing-function:可选的。规定动画的速度曲线。
  • animation-delay:可选的。规定动画何时开始,值可以是所有的整数。默认是 0。(这是一个实验中的功能,某些浏览器尚在开发中)
  • animation-iteration-count:可选的。规定动画被播放的次数。默认是 1。(这是一个实验中的功能,某些浏览器尚在开发中)
  • animation-direction:可选的。指示动画是否反向播放。(这是一个实验中的功能,某些浏览器尚在开发中)
  • animation-fill-mode:可选的。规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。
  • animation-play-state:可选的。规定动画是否运行或暂停。默认是 “running”。

将创建的动画绑定到一个指定的选择器上:

// 把 "myfirst" 动画捆绑到 div 元素,时长:5 秒:
div{
    animation: myfirst 5s;
    -webkit-animation: myfirst 5s; /* Safari 与 Chrome */
}

实现一个完全属性的动画——该动画只执行一次,且动画结束后停留在最后一帧的状态:

{animation: set_touch 1s ease 0s 1 normal forwards running;}

3、animation 的具体属性的解读如下

(1)、animation-name 属性

必须的。规定 @keyframes 动画的名称。

animation-name 属性的值:

  • none:特殊关键字,表示无关键帧。可以不改变其他标识符的顺序而使动画失效,或者使层叠的动画样式失效。
  • IDENT:标识动画的字符串,由大小写敏感的字母a-z、数字0-9、下划线(_)和/或横线(-)组成。第一个非横线字符必须是字母,数字不能在字母前面,不允许两个横线出现在开始位置。

(2)、 animation-duration 属性

必须的。指定一个动画周期的时长。默认是 0s,表示无动画。

  • <time>:一个动画周期的时长,单位为秒(s)或者毫秒(ms)。

案例:

// 一个值
{animation-duration: 6s;}

//多个值
{animation-duration: 10s, 30s, 230ms;}

(3)、animation-timing-function 属性

可选的。规定动画的速度曲线。

animation-timing-function 属性的值:

  • ease:默认值。动画开始时做加速运动,在结束前变慢。
  • ease-in:动画以低速开始。
  • ease-out:动画以低速结束。
  • ease-in-out:动画以低速开始和结束。
  • linear:动画始终保持匀速运动。
  • steps-start:表示动画是从时间段的开头连续。
  • steps-end:表示动画是从时间段的末尾连续。

函数值:

  • cubic-bezier() 函数:值必须在集合 [0, 1] 的浮点数集合里。
  • steps() 函数:指定了时间函数中的间隔数量(步数)。有两个参数:
    • 间隔数量(步数):必须的。一个正整数。
    • 动画的连续状态:表示动画是从时间段的开头连续还是末尾连续。
      • end:默认值,表示戛然而止。
      • start:表示直接开始。
  • frames() 函数:值是一个正整数。

案例:

// 一个值
{animation-timing-function: linear;}

// 多个值
{animation-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1.0, 0.1);}

// cubic-bezier() 函数
{animation-timing-function: cubic-bezier(0, 0.7, 1, 0.1);}

// steps() 函数
{animation-timing-function: steps(4, end);}

// frames() 函数
{animation-timing-function: frames(10);}

(4)、animation-delay 属性

可选的。规定动画何时开始,值可以是所有的整数。默认是 0。(这是一个实验中的功能,某些浏览器尚在开发中)

animation-delay 属性的值:

  • <time>:从动画样式应用到元素上到元素开始执行动画的时间差。该值可用单位为秒(s)和毫秒(ms)。

案例:

// 一个值
{animation-delay: 3s;}

// 多个值
{animation-delay: 2s, 4ms;}

(5)、animation-iteration-count 属性

可选的。规定动画被播放的次数。默认是 1。(这是一个实验中的功能,某些浏览器尚在开发中)

animation-iteration-count 属性的值:

  • infinite:无限循环播放动画。
  • <number>:动画播放的次数;默认值为1。可以用小数定义循环,来播放动画周期的一部分:例如,0.5 将播放到动画周期的一半。不可为负值。

案例:

// infinite
{animation-iteration-count: infinite;}

// <number>
{animation-iteration-count: 3;}

// 多个值
{animation-iteration-count: 2, 0.5, infinite;}

(6)、animation-direction 属性

可选的。指示动画是否反向播放。(这是一个实验中的功能,某些浏览器尚在开发中)

animation-direction 属性的值:

  • normal:默认值。正向运行动画,每周期动画循环结束,动画重置到起点重新开始。
  • alternate:动画交替反向运行,反向运行时,动画按步后退,同时,带时间功能的函数也反向。比如,ease-in 在反向时成为 ease-out。计数取决于开始时是奇数迭代还是偶数迭代。
  • reverse:反向运行动画,每周期动画循环结束,动画由尾到头运行。
  • alternate-reverse:反向交替, 反向开始交替。动画第一次运行时是反向的,然后下一次是正向,后面依次循环。决定奇数次或偶数次的计数从 1 开始。

案例:

// 一个值
{animation-direction: normal;}

// 多个值
{animation-direction: alternate, reverse, normal;}

(7)、animation-fill-mode 属性

可选的。规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。

animation-fill-mode 属性的值:

  • none:默认值。动画将不会将任何样式应用于目标。
  • forwards:动画停留在动画执行到最后一个关键帧的状态值。
  • backwards:动画恢复到第一个关键帧的状态值。
  • both:动画遵循 forwards 和 backwards 二者的规则,从而在两个方向上扩展动画属性。

案例:

// 单个值
{animation-fill-mode: backwards;}

// 多个值
{animation-fill-mode: both, forwards, none;}

(8)、animation-play-state 属性

可选的。规定动画是否运行或暂停。默认是 “running”。

animation-play-state 属性的值:

  • running:默认值。当前动画正在运行。
  • paused:当前动画已被停止。

案例:

// 单个值
{animation-play-state: paused;}

// 多个值
{animation-play-state: paused, running, running;}

二、transform + transition

CSS transform 属性
CSS transition 属性

1、transform——变形

用 transform 实现的动画必须用 transition 来驱动。

(1)、transform 2D 与 3D 的比较

transform 2D 与 3D 的比较表
2D 3D
属性 描述 属性 描述
- - backface-visibility 定义元素在不面对屏幕时是否可见。
- - transform-style 定义被嵌套元素如何在 3D 空间中显示。
- - perspective(n) 定义 3D 元素的透视效果。
transform-origin 改变元素的中心原点的位置。 perspective-origin 定义 3D 元素的底部的中心位置位置。
rotate(angle) 旋转。在一个给定度数顺时针旋转的元素。负值是允许的,这样是元素逆时针旋转。 rotate3d(x, y, z, angle) 同 2D 的 rotate。

- rotateX(angle)
- rotateY(angle)
- rotateZ(angle)
translate(x, y) 位移。根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动。

- translateX(n):沿着 X 轴移动元素。
- translateY(n):沿着 Y 轴移动元素。
translate3d(x, y, z) 同 2D 的 translate。

- translateX(n)
- translateY(n)
- translateZ(n)
scale(x, y) 缩放。该元素增加或减少的大小,取决于宽度(X轴)和高度(Y轴)的参数。

- scaleX(x):改变元素的宽度。
- scaleY(y):改变元素的高度。
scale3d(x, y, z) 同 2D 的 scale。

- scaleX(x)
- scaleY(y)
- scaleZ(z)
skew(x-angle, y-angle) 倾斜。包含两个参数值,分别表示X轴和Y轴倾斜的角度,如果第二个参数为空,则默认为0,参数为负表示向相反方向倾斜。

- skewX(angle):表示只在 X 轴(水平方向)倾斜。
- skewY(angle):表示只在 Y 轴(竖直方向)倾斜。
- -
matrix(n,n, n,n, n,n) 整合。将上面 2D 变化所有的方法整合成一个使用。使用 2x3 的矩阵。包含旋转,缩放,移动(平移)和倾斜功能。 matrix3d(n,n,n,n, n,n,n,n, n,n,n,n, n,n,n,n) 整合。将上面 3D 变化所有的方法整合成一个使用。使用 16 个值的 4x4 的矩阵。

(2)、transform 属性的使用

// translate——位移
div {
    transform: translate(50px, 100px);
    transition: transform 500ms;
}
 
// rotate——旋转
div {
    transform: rotate(30deg);
    transition: transform 500ms;
}
 
// scale——缩放
div {
    transform: scale(2, 3);
    transition: transform 500ms;
}
 
// skew——倾斜
div {
    transform: skew(30deg, 20deg);
    transition: transform 500ms;
}
 
// matrix——整合
div {
    transform:matrix(0.866, 0.5, -0.5, 0.866, 0, 0);
    transition: transform 500ms;
}

2、transition——过渡

从一种样式转变到另一种样式的过程叫做 过渡。

语法:

{ transition: property | duration | timing-function | delay }
  • transition-property:规定应用过渡的 CSS 属性的名称。
  • transition-duration:定义过渡效果花费的时间。默认是 0。
  • transition-timing-function:规定过渡效果的时间曲线。默认是 “ease”。
  • transition-delay:规定过渡效果何时开始。默认是 0。

(1)、transition 的实现

要实现这一点,必须定义好两项内容:

  • 指定要添加效果的CSS属性
  • 指定效果的持续时间。

例如:

// 定义宽度属性的过渡效果,时长为 2 秒
div{
    width: 100px;
    transition: width 2s;
    -webkit-transition: width 2s; /* Safari */
}

【注意】如果未指定的期限,transition 将没有任何效果,因为默认值是 0。

(2)、多项改变

要添加多个样式的变换效果,添加的属性由逗号分隔:

div{
    width: 100px;
    height: 100px;
    transform: rotateX(120deg);
    transition: width 2s, height 2s, transform 2s;
    -webkit-transition: width 2s, height 2s, -webkit-transform 2s;
}

三、案例

1、transform + @keyframes + animation 实现 loadding 加载

.iconfont-loadding {
  animation: start_loadding 800ms linear 100ms infinite normal none running;
}

@keyframes start_loadding {
  from { transform: rotate(0deg);}
  to { transform: rotate(360deg);}
}

进一步组件化:

// 封装一个使用动画的函数,接受一个表示位置的参数(通过调用这个函数就可以使用这个动画)
.entry-animation(@position: top) {
  animation: entry 800ms ease 100ms forwards;
  @keyframes entry {
    0% {
      @{position}: 0px;
      opacity: 0;
    }
    100% {
      @{position}: 50px;
      opacity: 1;
    }
  }
}
// 创建一个动画
@keyframes start_loadding {
  0% { transform: rotate(0deg);}
  100% { transform: rotate(360deg);}
}

【注意】经实际验证:

  • 关键字 from 和 to,以及百分比进度,是不能被抽离成变量的。
  • 对于 @keyframes <动画名>,其中“动画名”是不能被抽离成变量的。

2、transition 实现页面头部导航栏的颜色过渡变化

首先,假设在 template 里已经写好了页面头部导航栏,接下来要在 css 中定义好相关的类:

.dark {
  color: #333;
  background: rgba(255, 255, 255, 1);
  transition: color 3s, background 3s;
}
.light {
  color: #fff;
  background: rgba(255, 255, 255, 0);
  transition: color 3s, background 3s;
}
.empty {
  opacity: 0;
  transition: opacity 3s;
}

然后,在 js 中使用这些类:

export default {
  mounted () {
    window.addEventListener('scroll', this.handleScroll)
  },
  beforeDestroy () {
    window.removeEventListener('scroll', this.handleScroll)
  },
  methods: {
    // 监听页面滚动
    handleScroll (e) {
      let scrollTop = window.pageYOffset ||
      	document.documentElement.scrollTop ||
      	document.body.scrollTop
      if (scrollTop >=0 && scrollTop <= 30) {
        this.$refs.tagTopMenu.className = `tag-top-menu light`
      } else if (scrollTop >= 100) {
        this.$refs.tagTopMenu.className = `tag-top-menu dark`
      } else {
        this.$refs.tagTopMenu.className = `tag-top-menu empty`
      }
    }
  }
}

【遇到的问题】:

  • 在 vue 中 window.addEventListener(‘scroll‘, xxx) 监听失效,怎么办?

入参加上 true。让其在捕获阶段而非冒泡阶段执行这个监听。(如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。)

例如:

  mounted () {
    window.addEventListener('scroll', this.handleScroll, true)
  },
  beforeDestroy () {
    window.removeEventListener('scroll', this.handleScroll, true)
  }
  • 在 vue 中使用 document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset 这三个值都是 0,怎么办?

我这边是,代码里面写了 min-height: calc(100vh - 268px);,这个一直是不超出屏幕的。并且,我给父元素 div 加了 overflow-y: scroll; 实现了滚动条,但带来了现在的这个问题。可是又不得不加 overflow,否则我就可以通过改 overflow 来解决这个问题了。

此时,还有一种办法:改取 e.target 的 scrollTop 即可。

例如:

// 监听页面滚动
    handleScroll (e) {
      // let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      let scrollTop = e.target.scrollTop
      this.isShowTagTitle = false
      if (scrollTop <= 30) {
        this.$refs.tagTopMenu.className = `tag-top-menu light`
      } else if (scrollTop >= 130) {
        this.$refs.tagTopMenu.className = `tag-top-menu dark`
        this.isShowTagTitle = true
      } else {
        this.$refs.tagTopMenu.className = `tag-top-menu empty`
      }
    },

【参考】
vue中window.addEventListener(‘scroll‘, xx)失效解决办法
解决window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop获取距离顶部距离都为0的问题
为什么scrollTop设置后一直为0的解释和解决方案(精品)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值