## 動畫
### 談用戶界面設計
用戶界面設計是要圍繞著好用的,圍繞著用戶體驗的,它可以有固定的規范,又可以沒有既定的形式,是靈活的,多變的,可以墨守成規,也可以天馬行空,任何時候不能太過死板,死板是阻礙創新最大的障礙力量,不論如何,不論何時,只要是好用的、對用戶友好的設計就是好的設計。
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問題
- 臨時
- 好文
- 節流防抖