實現前端彈簧動效

彈簧動效是IOS系統原生自帶的一個效果,如在iPhone上面的照片點開大圖的展現效果就是一個彈簧動畫,以下圖所示:javascript

它有一個彈閃的過程,一大一小交替縮放就像一個彈簧在彈動同樣,而不是以往那種簡單的線性變大。css

若是使用CSS的animation-timing-function只是改變運動的速度,不能改變運動的方向。html

而本身手動寫CSS模擬這種先變大再變小的效果:前端

@keyframes spring-show {
    0% {
        transform: scale(0);
    }
    90% {
        transform: scale(1);
    }
    /* 先放大一點 */
    95% {
        transform: scale(1.1);
    }
    /* 而後再縮回去 */
    100% {
        transform: scale(1);
    }
}複製代碼

是沒有這種彈性動感的。vue

由於要實現一個彈簧振動效果,須要有兩個參數,一個是阻尼係數damping ration,另外一個是剛度stiffness,阻尼係數決定了衰減的快慢,剛度決定了往返的週期長短。給定這兩個參數和彈簧的始末位移,根據一些物理公式能夠推導出任意時刻彈簧的位移,這個位移就能夠看成上面的scale縮放的值,或者是translate、rotate等的值。java

那怎麼算呢?大漠在《CSS如何實現彈簧動畫效果》也詳細地討論了這種效果,並寫一個SASS函數實現,不過這種方式生成的CSS廣泛比較大,因此我改用了JS實現,原理都是計算一個CSS的keyframes關鍵幀動畫的在1%, 2%, 3%, ..., 100%的時候屬性值應該是多少,而後再動態地插入一個style標籤。這裏借用了一個css spring的庫,這個庫gzip後只有3KB,使用方法以下:git

import spring, { toString } from 'css-spring';
const keyframes = spring(
    { scale: 0 }, // from
    { scale: 1 }, // to
    // precision表示精度有2位
    { damping: 14, stiffness: 170, precision: 2}
);
const keyframeString = toString(keyframes);
console.log(keyframeString);複製代碼

生成的CSS以下圖所示:github

它會有一個大小的變化過程:0 -> 1 -> 1.1 -> 0.99 -> 1,把這些值畫成一個圖表看起來更加直觀:web

能夠看到它有一個抖動且週期衰減的過程,實際的效果以下圖所示:spring

除了放大,縮小也能這樣處理,還能夠應用於旋轉,效果以下圖所示:

這個是用下面的代碼生成的:

const keyframes = spring(
    { rotateZ: 30 }, // from
    { rotateZ: 0 }, // to
    { damping: 14, stiffness: 170, precision: 3}
);複製代碼

當咱們須要藉助animation-delay讓3個星星逐個出現的時候,須要先visibility: hidden隱藏而後再出現,這個時候須要在keyframes裏面添加visibility屬性,以下代碼所示:

let from = {rotateZ: '30', visibility: 'hidden' },
    to = {rotateZ: '0', visibility: 'visible' };
if (from.visibility) {
    keyframes['0%'].visibility = from.visibility;
    keyframes['1%'].visibility = to.visibility;
    // 最後結束animate-fill-mode: forwards使用
    keyframes['100%'].visibility = to.visibility;
}複製代碼

最後生成一個keyframes:

@keyframes spring-rotate {
    0% {transform:rotateZ(29.1deg);visibility:hidden;}
    1% {transform:rotateZ(27.507deg);visibility:visible;}
    /* ... */
    100% {transform:rotateZ(0deg);visibility:visible;}
}複製代碼

再讓每一個star星星的animation-delay依次增大:

.star {
    visibility: hidden;
    animation: spring-rotate .59s linear forwards;
}
.star:nth-of-type(2) {
    animation-delay: .15s;
}
.star:nth-of-type(3) {
    animation-delay: .3s;
}複製代碼

這樣就能實現逐個出現的效果了,以下圖所示:

這種彈簧動效可以加強動感,比普通的單向效果看起來更帶感。

在實際的實現中我寫了一個util,當頁面初始化的時候就生成keyframes,而後插入一個style標籤放在head裏面。由於若是再加上webkit前綴,一個keyframes有4KB,10個就有40KB,直接用JS動態計算的方式,會更省空間,靈活性也更強一點。


【人人網招聘中高級前端】

1. 項目背景: 咱們在作一個企業級海外的SAAS CRM(客戶管理系統)產品, 前端的技術挑戰很大, 好比在咱們的網站讓客戶直接打網絡電話(直接打手機那種), 發email, 自動根據用戶場景處理業務等。

2. 技術棧背景: 也是採用比較流行的vue, vuex等框架, 通信是WebRTC, 消息分發系統用Google的FCM和蘋果的APN。服務部署在亞馬遜或谷歌雲上。服務全球客戶。

3. 另外由於產品是一個企業級用戶產品因此個方面要求比較高(好比性能,安全,多任務處理等)。因此對候選人技術要求比較高,若是您對技術特別在乎,那麼咱們的空缺提供了很好的才能發揮空間和鍛鍊成長的機會。

請將簡歷發至shanshan.zhu@renren-inc.com


【其它文章】實現WebRTC P2P鏈接

相關文章
相關標籤/搜索