前言

 在《CSS魔法堂:Transition就这么好玩》中我们了解到对于简单的补间动画,我们可以通过transition实现。那到底多简单的动画适合用transtion来实现呢?答案就是——我们只需定义动画起始和结束帧的状态的动画。一旦关键帧数大于2时,我们必须转向CSS Animation了。本文为这段时间学习的记录,欢迎拍砖。

简单粗暴介绍CSS Animation 规则和属性

定义关键帧动画

语法:

@keyframes <Animation Name> {[<Animation Time Offset> {/* CSS Properties */}]*
}

示例:

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

注意项:
1.<Animation Name>的命名规范

// 命名需要遵循以下规则
const rIsInvalid = /^--|^[0-9]+-|^(?:unset|initial|inherit|none)$/, rIsValid = /^[0-9a-z-_\\]+$/i
function isValidAnimationName(animationName: string): boolean{return !rIsInvalid.test(animationName) && rIsValid(animationName)
}

2.<Animation Time Offset>取值
0-100%from,等价与0%to,等价与100%
3.<Animation Name>重复怎么办
@keyframes CSS规则不支持层叠样式,因此当出现多个同名keyframes,那么仅最后出现的那个有效。

/* 无效 */
@keyframes rotate {from { transform: rotate(0deg); }to { transform: rotate(360deg); }
}
/* 生效 */
@keyframes rotate {from { transform: rotate(90deg); }to { transform: rotate(-360deg); }
}

4.<Animation Time Offset>重复怎么办
与@keyframes CSS规则一样,标准规定相同的关键帧不产生层叠,仅最后出现的认定为有效。
但实际上FireFox14+和Chrome均将关键帧设计为可层叠的。

@keyframes rotate {from { transform: rotate(0deg); }from { background: red; }/* 上述两条time offset实际上等价于* from { transform: rotate(0deg); background: red; }*/to {transform: rotate(360deg);background: yellow;}
}

5.!important导致属性失效
一般情况下使用!important会让CSS属性获得最高权重,但在@keyframes下却会导致该CSS属性失效。

@keyframes rotate {from {transform: rotate(90deg);background: red!important; /* background属性无效 */}to { transform: rotate(-360deg); }
}

6.必须提供至少两个关键帧

/* 不会根据缓动函数产生动画效果,而是在动画持续时间的最后瞬间移动过去 */
@keyframes move-left{to {left: 100px;}
}

使用动画

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

示例:

.box.rotate {animation: rotate 10s infinite alternate;
}

子属性介绍

<animation-name>,指定通过@keyframes定义的补间动画名称。
<animation-duration>,动画持续时长,默认为0s。单位为s和ms。
<animation-delay>,动画播放延迟,默认为0s。单位为s和ms。
<animation-iteration-count>,动画重复播放次数,默认为1,infinite表示无限循环。动画播放总时长为<animation-duration>*<animation-iteration-count>
<animation-direction>,可选值为normal | reverse | alternate | alternate-reverse,分别表示动画播放顺序是从from到to从to到from从from到to再从to到from从to到from再从from到to注意:设置alternate|alternate-reverse时,animation-iteration-count必须大于1才能看到效果
<animation-fill-mode>,可选值为none | forwards | backwards | both,用于设置动画开始前和结束后是否应用0%100%的样式对元素上。分别表示不应用应用100%的样式延迟播放期间应用0%的样式0%和100%的样式均应用
注意:

  1. 默认情况下(none),动画结束后会恢复动画前的样式;
  2. 设置backwards时,值大于0才能看到效果。
    <animation-play-state>,可选值running | paused,获取和设置播放状态。注意:通过这个属性,我们仅能实现暂停和继续播放的效果,无法实现重播,更别说回放了
    <animation-timing-function>,用于设置缓动函数类型,值为ease | ease-in | ease-out | ease-in-out | linear | step-start | step-end | steps(<integer>, <flag>) | frames(<integer>) | cubic-bezier(<number>,<number>,<number>,<number>)
    其中ease | ease-in | ease-out | ease-in-out | linear | cubic-bezier(<number>,<number>,<number>,<number>)的效果均为连续渐变的,而step-start | step-end | steps(<integer>, <flag>) | frames(<integer>)则为突变效果。下面我们深入理解后者吧。

缓动函数-step解疑专题

step-start实际上等价于steps(10, start),而step-end则等价于steps(10),所以我们只要理解好steps(<integer>, <flag>)即可。

/* 通过设置在一个动画周期内(<animation-duration>)的平均刷新帧数,实现突变动效。具体应用有:游戏精灵行走、打字效果等* <number_of_steps> - 两个关键帧间的刷新次数* <direction> - 方向,可选值为 end | start。*               end为默认值,表示动画一结束,动画效果就结束;*               start表示动画一开始就马上执行完第一个关键帧的效果。*/
steps(<number_of_steps>, <direction>)

从张旭鑫那偷来的解释:
start:表示直接开始。也就是时间才开始,就已经执行了一个距离段。于是,动画执行的5个分段点是下面这5个,起始点被忽略,因为时间一开始直接就到了第二个点:

end:表示戛然而止。也就是时间一结束,当前距离位移就停止。于是,动画执行的5个分段点是下面这5个,结束点被忽略,因为等要执行结束点的时候已经没时间了:

另外通过将<animation-fill-mode>设置为forwards,那么当<direciton>设置为end时,也会显示(保持)动画最后一个关键帧的样式。

事件

const target = document.getElementById("target")
target.addEventListener("animationstart", e => {// 动画开始时触发
})
target.addEventListener("animationiteration", e => {// 每次重复执行动画时触发// 当<animation-iteration-count>为1时,不会触发。
})
target.addEventListener("animationend", e => {// 当动画结束时触发
})

搞尽脑汁实现重播效果

到这里我们已经可以通过@keyframes定义和应用CSS Animation了,但我们能否获取对动画效果更多的控制权呢?如开始、暂停、继续、重播。通过<animation-play-state>我们能轻易实现开始、暂停和继续的效果,但重播却没那么容易。

function pause (target: HTMLElement):boolean {const isRunning = target.style.animationPlayState == "running"if (isRunning) {target.style.animationPlayState = "paused"}return isRunning
}function play (target: HTMLElement):boolean {const isStop = target.style.animationPlayState == "paused"if (isStop) {target.style.animationPlayState = "running"}return isStop
}function replay (target: HTMLElement, animationClassName: string):void {// 先移除动画效果target.classList.remove(animationName)// requestAnimationFrame的回调函数会在下一次界面渲染前执行requestAnimationFrame(_ => {// 这时动画的影响还在,所以要等界面渲染完后再重新启用动画效果,才能实现重播requestAnimationFrame(_ => {target.classList.add(animationName)})})
}

总结

CSS3为我们提供了动画效果,除了提供比Transition更丰富的可控性,比JavaScript更简易的API,还让我们可以使用GPU来加速呢^^
尊重原创,转载请注明来自:https://www.cnblogs.com/fsjohnhuang/p/9289618.html ^
^肥仔John

参考

https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes
https://designmodo.com/steps-css-animations/
http://lea.verou.me/2011/09/pure-css3-typing-animation-with-steps/
http://jsfiddle.net/simurai/CGmCe/
https://www.zhangxinxu.com/wordpress/2018/06/css3-animation-steps-step-start-end/

CSS魔法堂:更丰富的前端动效by CSS Animation相关推荐

  1. 如何选取合适的前端动效方案?

    一.原因 前端动画场景需求多 对众多动画场景的技术实现方案选择上比较模糊 各动画方案的优劣及适用场景认识模糊 现有动画库太多,不知道选哪个 主流动画库的适用场景认识模糊 二.分类 动画用途 展示型的动 ...

  2. CSS魔法堂:你一定误解过的Normal flow

    前言  刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...

  3. CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins

    前言   盒子模型作为CSS基础中的基础,曾一度以为掌握了IE和W3C标准下的块级盒子模型即可,但近日在学习行级盒子模型时发现原来当初是如此幼稚可笑.本文尝试全面叙述块级.行级盒子模型的特性.作为近日 ...

  4. CSS魔法堂:重拾Border之——图片作边框

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  5. CSS魔法堂:重拾Border之——更广阔的遐想

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  6. CSS魔法堂:说说Float那个被埋没的志向

    前言  定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...

  7. CSS魔法堂:那个被我们忽略的outline

    前言  在CSS魔法堂:改变单选框颜色就这么吹毛求疵!中我们要模拟原生单选框通过Tab键获得焦点的效果,这里涉及到一个常常被忽略的属性--outline,由于之前对其印象确实有些模糊,于是本文打算对其 ...

  8. CSS魔法堂:深入理解line-height和vertical-align

    前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊 ...

  9. CSS魔法堂:那个被我们忽略的outline 1

    前言  在CSS魔法堂:改变单选框颜色就这么吹毛求疵!中我们要模拟原生单选框通过Tab键获得焦点的效果,这里涉及到一个常常被忽略的属性--outline,由于之前对其印象确实有些模糊,于是本文打算对其 ...

最新文章

  1. linux php mysql安装完整版本_Linux下安装PHP+MySQL+Apache完整版
  2. 第一百一十四节,JavaScript文档对象,DOM进阶
  3. java线程协作_java 线程间的协作
  4. Linux安装无法运行install,linux 无法 安装swoole
  5. Java 数组及多维数组
  6. 1.文档数据非结构化
  7. Python 面向对象(OOP)基本概念
  8. 基于品类关系,虚拟类目如何建设?
  9. 堆排序算法(C#实现)
  10. 使用Unity3D编写ARPG游戏——角色属性的定义与实现(一)
  11. oracle 倒库详细步骤,详细的“倒车入库”步骤来了!一图一解析,照着做考试轻松一把过...
  12. 易语言API获取进程程序路径
  13. uniapp中后端返回的数字字符串如何在页面快速计算
  14. elk之拼音插件可选参数
  15. Java设计模式之Builder模式
  16. win10软件安装出现错误代码2503/2502,解决方案
  17. 轻松搞定RabbitMQ开篇:Java消息队列与JMS的诞生
  18. 用python3写一个小球转动的抽奖小游戏
  19. 大数据时代下的智慧育种,百奥云获数千万元Pre-A轮融资
  20. USB摄像头设置采集亮度和对比度

热门文章

  1. 操作系统内存管理-Linux版
  2. Flutter开发之ListView组件(21)
  3. jar容器部署成功无法访问_Spring Boot 应用程序五种部署方式
  4. cesium加载百度地图_四大Webgis地图框架的对比选择
  5. [转载]什么情况下应该设置 cudnn.benchmark = True?
  6. css3的动画特效--动画序列(animation)
  7. AndroidStudio(1 下载安装,环境搭建,使用设置)
  8. 【动态树】[BZOJ2002] Bounce 弹飞绵羊
  9. 防止用户利用PHP代码DOS造成用光网络带宽
  10. 跨平台C++开发环境搭建——GNU+STL+Boost+wxWidget+OpenSceneGraph