## 动画
### 谈用户界面设计
用户界面设计是要围绕着好用的,围绕着用户体验的,它可以有固定的规范,又可以没有既定的形式,是灵活的,多变的,可以墨守成规,也可以天马行空,任何时候不能太过死板,死板是阻碍创新最大的障碍力量,不论如何,不论何时,只要是好用的、对用户友好的设计就是好的设计。
2017-10-2 13:53:25
* * * * *
[干货教程!12个常用动画原理(官方全系列)](http://www.365yg.com/item/6466630715202077197/)
* * * * *
### 动画浅析
赖来看一个 模态窗的(位置)状态案列:
1. 进入前
`……进入过程`
2. 已进入
`……离开过程`
3. 已离开
**这三个状态都是稳定的状态**,只有中间的两个过程是动态的,也就是我们所看到的动画效果。
动画总是从一个状态(形态)到另一个状态(形态),也就是从一个点到另一点,这几个点就是骨架,就是顶点,是稳定的,每一个点都是一个要着重表现的状态。中间变化轨迹的就是具体的过度动画了。
动画的本质也就是过度,从一帧过度到另一帧,只不过由于人眼的视觉暂留原理,是我们感觉这种帧的切换很流畅,也就是我们所说的动画。
理解这些,理解顶点,理解状态变化,我们就明白了为什么要在程序中设计动画交互了,因为状态的变化传达出了UI的状态,也就是那些顶点。而中间的动画也是有重要意义的,因为人是情感动物,是带着情感去理解事物的,所以动画的过程细腻地表现了程序的交互状态,帮助使用者更好的理解程序所表达的意图,使其有更好的交互体验。
* * * * *
### 动画效果
屏幕视口就是一个舞台。
入场:缩小、淡入。
出场:放大、淡出。
锤子科技的设计还是挺有品味的。
* * * * *
### 动画思考
**元素动画体现有三点:**
1. 位置改变
2. 大小改变(宽高、内外边距、边框)
3. 外观改变(背景颜色、透明度、旋转、变形、阴影等效果)
**动画根据影响分类,有两种:**
1. 会影响DOM布局的变化的(布局有害)
2. 不会影响DOM布局的变化的(布局无害)
一般,`位置改变`、`大小改变`也有“会影响DOM布局的变化”和“不会影响DOM布局的变化”的两种方式。
想要不改变DOM布局(元素在文档流文档流内的布局,或影响其他元素的布局),就不能使用常规的手段去改变元素,比如使用css3放大来代替传统宽高的改变,使用css3偏移来代替传统的使用边距的方式来改变元素位置。
不过有的动画也可能使用了 会影响DOM布局的变化 的方式,不过这样性能低一些,动画时会改变其他元素的位置,页面布局,会发生重绘,但是有些时候这样动画场景会更生动,具体看情况。只要知道DOM布局在动画中有这两种方式表现即可。
**布局有害的例子:**
```
display
width、margin、padding、border
```
**布局无害的例子:**
```
visibility、opacity
transform、outline
```
* * * * *
### 动画的本质
动画:会动的画面,即切换的帧。
动画的本质就是帧的切换,而实际上我们所说的动画就是那些比较自然流畅的帧切换。所以动画的本质就是帧的过度了 —— 动画的本质就是过度。动画效果就是过渡效果。
过度的平稳,细腻,那么这个动画就更流畅,真实。
* * * * *
### 动画实现
[layer弹层组件移动版](http://layer.layui.com/mobile/)
底部对话框: `layui-m-anim-up`
```css
/* el class: layui-m-layerchild layui-m-layer-footer layui-m-anim-up */
body .layui-m-layer .layui-m-layer-footer {
position: fixed;
width: 95%;
max-width: 100%;
margin: 0 auto;
left: 0;
right: 0;
bottom: 10px;
background: 0 0;
}
@-webkit-keyframes layui-m-anim-up {
0% {
opacity: 0;
-webkit-transform: translateY(800px);
transform: translateY(800px)
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0)
}
}
.layui-m-anim-up {
-webkit-animation-name: layui-m-anim-up;
animation-name: layui-m-anim-up
}
```
询问框: `layui-m-anim-scale`
```css
/* el class: layui-m-layerchild layui-m-anim-scale */
.layui-m-anim-scale {
animation-name: layui-m-anim-scale;
-webkit-animation-name: layui-m-anim-scale;
}
@keyframes layui-m-anim-scale {
0% {
opacity: 0;
-webkit-transform: scale(.5);
transform: scale(.5)
}
100% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1)
}
}
.layui-m-anim-scale {
animation-name: layui-m-anim-scale;
-webkit-animation-name: layui-m-anim-scale;
}
```
* * * * *
[WeUI](https://weui.io/#actionsheet):`weui-actionsheet weui-animate-slide-up`
不同设备,动画效果与样式不同(ios:`up/down`、android:`in/out`)。
~~~html
<script type="text/javascript">
// ios
$(function(){
var $iosActionsheet = $('#iosActionsheet');
var $iosMask = $('#iosMask');
function hideActionSheet() {
$iosActionsheet.removeClass('weui-actionsheet_toggle');
$iosMask.fadeOut(200);
}
$iosMask.on('click', hideActionSheet);
$('#iosActionsheetCancel').on('click', hideActionSheet);
$("#showIOSActionSheet").on("click", function(){
$iosActionsheet.addClass('weui-actionsheet_toggle');
$iosMask.fadeIn(200);
});
});
// android
$(function(){
var $androidActionSheet = $('#androidActionsheet');
var $androidMask = $androidActionSheet.find('.weui-mask');
$("#showAndroidActionSheet").on('click', function(){
$androidActionSheet.fadeIn(200);
$androidMask.on('click',function () {
$androidActionSheet.fadeOut(200);
});
});
});
</script>
~~~
出场时直接添加出场类。
也是在出场动画结束时移除节点的。
```javascript
$actionSheet.addClass(isAndroid ? 'weui-animate-fade-out' : 'weui-animate-slide-down');
$actionSheetMask.addClass('weui-animate-fade-out').on('animationend webkitAnimationEnd', function () {
$actionSheetWrap.remove();
_sington = false;
callback && callback();
});
```
```css
@keyframes a {
0% {
-webkit-transform: translate3d(0,100%,0);
transform: translate3d(0,100%,0)
}
to {
-webkit-transform: translateZ(0);
transform: translateZ(0)
}
}
.weui-animate-slide-up {
-webkit-animation: a ease .3s forwards;
animation: a ease .3s forwards
}
@keyframes b {
0% {
-webkit-transform: translateZ(0);
transform: translateZ(0)
}
to {
-webkit-transform: translate3d(0,100%,0);
transform: translate3d(0,100%,0)
}
}
.weui-animate-slide-down {
-webkit-animation: b ease .3s forwards;
animation: b ease .3s forwards
}
@keyframes c {
0% {
opacity: 0
}
to {
opacity: 1
}
}
.weui-animate-fade-in {
-webkit-animation: c ease .3s forwards;
animation: c ease .3s forwards
}
@keyframes d {
0% {
opacity: 1
}
to {
opacity: 0
}
}
.weui-animate-fade-out {
-webkit-animation: d ease .3s forwards;
animation: d ease .3s forwards
}
```
* * * * *
有弹性感觉的动画:
```css
@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}
45%{-webkit-transform:scale(1.05);transform:scale(1.05)}
80%{-webkit-transform:scale(.95);transform:scale(.95)}
to{-webkit-transform:scale(1);transform:scale(1)}
}
@keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}
45%{-webkit-transform:scale(1.05);transform:scale(1.05)}
80%{-webkit-transform:scale(.95);transform:scale(.95)}
to{-webkit-transform:scale(1);transform:scale(1)}
}
@-webkit-keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);ovisibility: visible;}
to{-webkit-transform:scale(.5);transform:scale(.5);visibility: hidden;}
}
@keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);visibility: visible;}
to{-webkit-transform:scale(.5);transform:scale(.5);visibility: hidden;}
}
```
**注意:元素的display发生改变(显示与不显示切换时),动画会重新运行一遍**
```css
display: none;
/* display: block; */
visibility: hide; /* 不会这样 */
```
* * * * *
**分析:**
可以看到所有的动画,都被定义了,**每个动画定义了一个专门的类,将动画定义部分都单独剥离出来了,这样方便使用,能提高可维护性。** 比如:`[class~=anim]` 都为动画定义类。(**动画帧名 和 动画类名 相同**)
而动画的原理为:不应用动画时,**默认就是元素最终的位置**(动画类只是通过 变形/放大/偏移 等方式改变元素的形态和空间位置,**并不会对元素的文档流布局产生任何影响,这点很重要**,所以任何元素都可以添加动画类,并且是无害的),动画的`0% 帧`**把元素置为动画帧起点**(起点位置一般会隐藏元素,元素的初始状态),而`100% 帧`将元素所有转换(位移,变换等)效果移除,**恢复为正常状态,即为默认状态 —— 元素最终的位置。** (`@keyframes`自带过渡效果,所以帧的变换就成了动画了)
元素类定义只定义最终的,动画类 专门定义动画,开始到结束。定义部分 无需关心 动画部分,只关心元素本身就可以了,这样就相当于解耦了,也就是实现**关注点分离。**
* * * * *
### 关于动画类的细节
如果一个动画处于未完成的状态,突然将类移去,那么元素就立即恢复原样,失去动画效果,所以如果要去掉动画类,必须等到动画运行完毕后再去除。
并且重复添加动画类,也只会触发一次动画。
所以如果要多次运行动画效果,就只能**安全的移除动画类**,然后再添加。
那么问题来了,要怎么铺捉到动画完成呢?
https://daneden.github.io/animate.css/ demo上有个例子:
```javascript
function testAnim(x) {
$('#animationSandbox').removeClass().addClass(x + ' animated').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
$(this).removeClass();
});
};
$(document).ready(function(){
$('.js--triggerAnimation').click(function(e){
e.preventDefault();
var anim = $('.js--animations').val();
testAnim(anim);
});
$('.js--animations').change(function(){
var anim = $(this).val();
testAnim(anim);
});
});
```
可以看到,时机就是 `webkitAnimationEnd` 事件完成后,很明显这是一个动画结束事件。
元素动画结束事件,自然结束时触发,那么移除动画类导致的元素的动画效果停止,会不会触发呢。
> js能监听css3的动画结束事件,那能不能控制动画过程了呢?比如停止,暂停动画。
* * * * *
### 入场出场交错冲突问题
比如在入场动画进行时,用户点击取消了,那么此时在入场未完成的情况下要出场,这是怎么办。
如果直接移除入场类,那么元素将失去动画效果,回到本来的原点。
待实验……
* * * * *
### 动画实验
#### css动画版本
1. 连续添加相同的动画类没有用,动画只会运行一次。
2. 移除动画类,元素会回到没有动画类的初始状态。
3. 动画运行阶段,移除当前动画类,添加另一个动画类,元素突然回到无动画类的原点位置(一闪而过),再开始另一个动画。
4. 动画运行阶段,包括动画运行结束后,追加另一个动画类,没有作用,不会运行第二个动画。(jQuery中重复追加相同的类名只会有一个)
思考:当元素接受到新动画的指令时,如何由第一个动画平滑的转变运行第二个动画呢(即实现运行第二个动画时,起点就在当前位置,也就是要保留当前第一个动画的运行时场景、状态,就像进程调度一样,操作系统需要保存进程的状态,以便CPU再次切换回来时,能接着之前的状态继续工作),而不是第三种情况的那样立即失去动画效果,回到原点,一闪而过的那样非常不好。
~~~
不能中途离场,那么只能折中了,正确的效果就是等第一个动画运行完毕后才开始执行第二个动画。并且入场出场要衔接上,那么就要要求,第一个动画的结束就是第二个动画的开始状态,这个css里面可以设置。
animation-play-state: paused
可以暂停动画,但是能实现暂停后,转向另一个动画吗?
fill-mode 控制动画结束后的位置
想到好的办法了,或许可以解决两个动画交替不能衔接的问题,方法就是,问题就在第二个动画开始时的状态,如果不设置 `to 0%` 直接设置 `to 100%` 不就没有这个问题了,不就可以直接由当前第一个动画顺畅过度执行第二个动画,第二个动画没有 `to 0%` ,不就没有闪动问题了吗? 待实验。
~~~
#### js版本
待实验……
项目地址:https://coding.net/u/xiasf/p/animation-test/git
> 要理解动画,就要深入理解浏览器中js的工作原理,以及dom操作和渲染的细节,js是单进程的,js进程和渲染进程是互斥的。
* * * * *
### 扩展资料
[CSS VS JS动画,哪个更快](http://www.toutiao.com/i6303459255865311746/)
[前端工程师CSS实例,加载动画](https://www.ixigua.com/i6457837281670595085/?utm_medium=feed_steam&utm_source=toutiao#mid=3529526410)
[css动画:纯css实现灰太狼头像制作](http://www.toutiao.com/i6419085161446507010/)
[css动画——动态渐变的效果](http://www.toutiao.com/i6405363758729789954/)
[为什么老式电视比液晶电视伤眼睛,高速摄像机为你揭开其中奥秘](https://www.ixigua.com/i6514458568677130765/?utm_source=toutiao&utm_medium=feed_stream#mid=83935140651)
[为什么手机拍摄快速移动的物体图像会变形?用超牛的画面来揭示](https://www.365yg.com/i6515267191212868099)
[视觉暂留详解:请不要相信你的眼睛,片头试验很神奇,请配合哦](https://www.ixigua.com/i6515684983825236493/?utm_source=toutiao&utm_medium=feed_stream#mid=83935140651)
[让你彻底搞懂前端路由前世今生!](https://www.toutiao.com/a6517043046805144067/?tt_from=weixin&utm_campaign=client_share×tamp=1517478446&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1)
[几种 JavaScript 动画库推荐](http://mp.weixin.qq.com/s/K7Q85nBkvSH-JXxqhsbyWg)
[前端,react,动画](https://tech.youzan.com/react-animations/)
[腾讯浏览服务-前端技术文档](http://x5.tencent.com/tbs/guide/tech.html#/)
[盒子端 CSS 动画性能提升研究](https://mp.weixin.qq.com/s/buywVtqnFXxyy4v40F7yKw)
[CSS动画:animation、transition、transform、translate傻傻分不清](https://mp.weixin.qq.com/s/-QTPwc8byT9kvn4m5JZSQA)
```css
.slider-slogan .btn-g a:hover {
transform: scale(1.1);
animation-fill-mode: backwards;
}
/* animation-fill-mode和再次设置元素变换有关,不这样设置,再次变换没有效果 */
```
[Web 动画帧率(FPS)计算](https://mp.weixin.qq.com/s/RbWeh0qfNHnXlotHLQOq8g)
[SVG Path路径在网页开发的作用](https://mp.weixin.qq.com/s/r7ZnAwQsxjRkq9j0LA5MHQ)
> 完美的骨骼过度动画
[CSS3 animation属性中的steps功能符深入介绍 « 张鑫旭-鑫空间-鑫生活](https://www.zhangxinxu.com/wordpress/2018/06/css3-animation-steps-step-start-end/)
#### 动画不可不知的细节(那些不为人知的秘密)
[【前端性能】Web 动画帧率(FPS)计算 - ChokCoco - 博客园](https://www.cnblogs.com/coco1s/archive/2017/12/13/8029582.html)
[浏览器的 16ms 渲染帧 - CSDN博客](https://blog.csdn.net/crystal6918/article/details/77361495)
[浏览器的 16ms 渲染帧--摘抄 - 刘浩2561179983 - 博客园](https://www.cnblogs.com/liuhao-web/p/8266872.html)
[HTML5探秘:用requestAnimationFrame优化Web动画 – WEB骇客](http://www.webhek.com/post/requestanimationframe.html)
[requestAnimationFrame 方法你真的用对了吗? - 前端经验分享 - SegmentFault 思否](https://segmentfault.com/a/1190000010229232)
[requestAnimationFrame,Web中写动画的另一种选择 - 刘哇勇 - 博客园](https://www.cnblogs.com/Wayou/p/requestAnimationFrame.html)
[贝塞尔曲线的一些事情_Animation, Web动画 教程_w3cplus](https://www.w3cplus.com/animation/mathematical-intuition-behind-bezier-curves.html)
[【转载】运动曲线提升CSS动画效果](https://mp.weixin.qq.com/s/oTriaa3Y64F3SoXhfaQKFg)
> 贝塞尔曲线的创造就是一个奇迹。 它们一开始是被用于计算机图形学来绘制形状,并且被用在Sketch和Adobe Illustrator这类工具中来绘制矢量图形。三次Bezier曲线使用如此广泛的原因是它们用起来非常方便:我们只需要改变4个不同点的位置,然后创造我们需要的曲线。
[前端动画效果实现的简单比较](https://mp.weixin.qq.com/s/tOhCWTLVzVdX07SaJYVEPg)
[有趣的CSS弹跳动画](https://mp.weixin.qq.com/s/LRbUyKw_0Ko3MK33kruSUw)
* * * * *
last update:2018-7-19 19:37:59
- 开始
- 微信小程序
- 获取用户信息
- 记录
- HTML
- HTML5
- 文档根节点
- 你真的了解script标签吗?
- 文档结构
- 已经落后的技术
- form表单
- html实体
- CSS
- css优先级 & 设计模式
- 如何编写高效的 CSS 选择符
- 笔记
- 小计
- flex布局
- 细节体验
- Flex
- Grid
- tailwindcss
- JavaScript
- javascript物语
- js函数定义
- js中的数组对象
- js的json解析
- js中数组的操作
- js事件冒泡
- js中的判断
- js语句声明会提前
- cookie操作
- 关于javascript你要知道的
- 关于innerHTML的试验
- js引擎与GUI引擎是互斥的
- 如何安全的修改对象
- 当渲染引擎遇上强迫症
- 不要使用连相等
- 修改数组-对象
- 算法-函数
- 事件探析
- 事件循环
- js事件循环中的上下文和作用域的经典问题
- Promise
- 最佳实践
- 页面遮罩加载效果
- 网站静态文件之思考
- 图片加载问题
- 路由及转场解决方案
- web app
- 写一个页面路由转场的管理工具
- 谈编程
- 技术/思想的斗争
- 前端技术选型分析
- 我想放点html模板代码
- 开发自适应网页
- 后台前端项目的开发
- 网站PC版和移动版的模板方案
- 前后端分离
- 淘宝前后端分离
- 前后端分离的思考与实践(一)
- 前后端分离的思考与实践(二)
- 前后端分离的思考与实践(三)
- 前后端分离的思考与实践(四)
- 前后端分离的思考与实践(五)
- 前后端分离的思考与实践(六)
- 动画
- 开发小技巧
- Axios
- 屏幕适配
- 理论基础
- 思考
- flexible.js原理
- 实验
- rem的坑,为什么要设置成百分比,为什么又是62.5%
- 为什么以一个标准适配的,其它宽度也能同等适配
- 自适应、响应式、弹性布局、屏幕适配
- 适配:都用百分比?
- 番外篇
- 给你看看0.5px长什么样?
- 用事实证明viewport scale缩放不会改变rem元素的大小
- 为什么PC端页面缩放不会影响rem元素
- 究竟以哪个为设备独立像素
- PC到移动端初试
- 深入理解px
- 响应式之栅格系统
- 深入理解px(二)
- 一篇搞定移动端适配
- flex版栅格布局
- 其他
- 浏览器加载初探
- 警惕你的开发工具
- JS模块化
- webpack
- 打包原理
- 异步加载
- gulp
- 命名规范
- 接口开发
- sea.js学习
- require.js学习
- react学习
- react笔记
- vue学习
- vue3
- 工具、技巧
- 临时笔记
- 怎么维护好开源项目
- 待办
- 对前端MVV*C框架的思考
- jquery问题
- 临时
- 好文
- 节流防抖