• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Web Animations 與 Angular動畫

    標簽: angular  javascript  css  web

    什么是Web Animations

    概述

    正如CSS Animations一樣,Web Animations是javascript提供的一組動畫接口,它允許同步和定時更改網頁的呈現, 即DOM元素的動畫。因此,使用Web Animations可以方便地用Js操作動畫,而不再需要像之前那樣寫一大堆css和定時器來實現。

    兼容性

    它目前尚屬W3C的標準草案,詳情可查閱:https://www.w3.org/TR/web-animations/ ,因此很多瀏覽器并不能完整支持,兼容性查詢

    正因如此,W3C官方為開發者提供了web-animations/web-animations-js polyfill插件,是我們能通過插件來解決瀏覽器的支持問題,插件地址:https://github.com/web-animations/web-animations-js/tree/master

    <script src="web-animations.min.js"></script>

    如上所示插入插件,即可使用Web Animations進行開發。

    代碼示例

    提供了很簡潔明了的,我們可以在 dom 元素上直接調用的 animate 函數:

    var element = document.querySelector('.animate-me');
    var animation = element.animate(keyframes, 1000);

    第一個參數是一個對象數組,每個對象表示動畫中的一幀:

    var keyframes = [
      { opacity: 0 },
      { opacity: 1 }
    ];

    這與 css 中的 keyframe 定義類似:

    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }

    第二個參數是 duration,表示動畫的時間。同時也支持在第二個參數中傳入配置項來指定緩動方式、循環次數等:

    var options = {
      iterations: Infinity, // 動畫的重復次數,默認是 1
      iterationStart: 0, // 用于指定動畫開始的節點,默認是 0
      delay: 0, // 動畫延遲開始的毫秒數,默認 0
      endDelay: 0, // 動畫結束后延遲的毫秒數,默認 0
      direction: 'alternate', // 動畫的方向 默認是按照一個方向的動畫,alternate 則表示交替
      duration: 700, // 動畫持續時間,默認 0
      fill: 'forwards', // 是否在動畫結束時回到元素開始動畫前的狀態
      easing: 'ease-out', // 緩動方式,默認 "linear"
    };
    var animation = element.animate(keyframes, options);

    在 dom 元素上調用 animate 函數之后返回一個 Animation 對象,或者通過 ele.getAnimation 方法獲取 dom 上的 Animation 對象。

    Animation對象有一些屬性和方法,比如:

    • Animation.finished(此動畫的當前完成的狀態,只讀)
    • Animation.effect(與此動畫相關聯的關鍵幀)
    • Animation.play()(開始播放動畫)
    • Animation.pause()(暫停播放動畫)

    等等。

    Animation對象還有兩個事件處理程序:

    • Animation.oncancel:獲取并設置取消事件的事件處理程序
    • Animation.onfinish:獲取并設置完成事件的事件處理程序

    由以上API,開發者可以通過 promiseevent 兩種方式對動畫進行操作:

    // 通過監聽事件進行處理
    myAnimation.onfinish = function() {
      element.remove();
    }
    // 通過承諾進行處理
    myAnimation.finished.then(
        () => element.remove()
    )

    與CSS動畫相比的優點

    低耦合

    CSS 動畫中,如果需要控制動畫或者過渡的開始或結束只能通過相應的 dom 事件來監聽,并且在回調函數中操作,這也是受 CSS 本身語言特性約束所致。也就是說很多情況下,想要完成一個動畫需要結合 CSS 和 JS 來共同完成。使用 WAAPI 則有 promise 和 event 兩種方式與監聽 dom 事件相對應。從代碼可維護性和完整性上看 WAAPI 有自身語言上的優勢。

    兼容性和流暢度

    事實上Web Animations常用方法現在已經兼容了大部分現代的瀏覽器。如果想現在就玩玩,可以使用官方提供的polyfill。而CSS動畫我們也用了很久,基本上對于老舊的瀏覽器只能用一些優雅的降級方案。至于流暢度的問題兩者性能差距不大,而且Web Animations提供了性能優化的方案。

    Angular中的Web Animations動畫

    概述,及引入方法

    Angular動畫是基于標準的Web動畫API(Web Animations API)構建的,它們在支持此API的瀏覽器中會用原生方式工作。

    上述是官方文檔對于Angular動畫的解釋。由于基于Web Animations,因此很多寫法也是非常相像的。

    和http、form一樣,Angular中的動畫也是一個獨立模塊,首先需在根模塊進行導入:

    import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
    // ...(其它模塊)
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserAnimationsModule,
        // ...(其它模塊)
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

    就在組件里去定義動畫了,如果需要定義大量的動畫片段,建議單獨建立一個項目的動畫模塊。當然,定義動畫之前需要引入一些常用的API:

    import { trigger, state, style, transition, animate, keyframes } from '@angular/animations';

    基本寫法

    import {
      Component,
      Input
    } from '@angular/core';
    import {
      trigger,
      state,
      style,
      animate,
      transition
    } from '@angular/animations';
    
    @Component({
      selector: 'app-hero-list-basic',
      template: `
        <h1 [@clickAnim]="state"
            (click)="toggleState()">
            點擊觸發
        </h1>
      `,
      styleUrls: [],
      animations: [
        trigger('clickAnim', [
          state('inactive', style({
            backgroundColor: '#eee',
            transform: 'scale(1)'
          })),
          state('active',   style({
            backgroundColor: '#cfd8dc',
            transform: 'scale(1.1)'
          })),
          transition('inactive => active', animate('100ms ease-in')),
          transition('active => inactive', animate('100ms ease-out'))
        ])
      ]
    })
    export class HeroListBasicComponent {
    
        constructor(public state = 'inactive') { }
    
        toggleState() {
            this.state = this.state === 'active' ? 'inactive' : 'active';
        }
    }

    上述代碼在@Component元數據中構建了一個名為clickAnim的簡單動畫,它會讓<h1>元素在兩個狀態activeinactive之間轉場, 當處于active**狀態時,它會把該元素顯示得稍微大一點、亮一點。模板中用[@triggerName]語法即可調用。

    Angular動畫圖解

    狀態(state)

    在此動畫中,我們可以為每個動畫狀態定義了一組樣式:

    state('inactive', style({
      backgroundColor: '#eee',
      transform: 'scale(1)'
    })),
    state('active',   style({
      backgroundColor: '#cfd8dc',
      transform: 'scale(1.1)'
    })),

    這些state具體定義了每個狀態的最終樣式,也就是說,這里其實并不只是在定義動畫,而是在定義該元素在不同狀態時應該具有的樣式。

    除了自定義狀態,還有兩種特殊狀態:

    1. void:匹配尚未被添加進來或者已經被移除了的狀態,用于進場或離場動畫
    2. *:匹配任何動畫的狀態

    transition()

    而負責這定義兩組樣式轉換的則是transition()函數,它的第一個參數負責定義需被轉換的狀態名稱(可定義多個):

    transition('inactive => active', animate('100ms ease-in')),
    transition('active => inactive', animate('100ms ease-out'))

    其中,=> 也可以寫成 <=> 即雙向的。

    第二個參數是一個animate()函數或一個數組,負責定義動畫執行的總時間以及樣式,當有些樣式只希望在動畫過程中生效,結束后并不保留,可以在數組中定義一個style()函數:

    transition('inactive => active', [
      style({
        backgroundColor: '#cfd8dc',
        transform: 'scale(1.3)'
      }),
      animate(
        '80ms ease-in', 
        style({
            backgroundColor: '#eee',
            transform: 'scale(1)'
        })
      )
    ]),

    關鍵幀

    上述代碼中,關于動畫運行的方式,用了ease-inease-out兩種方法,除此之外還有幾種,例如linear等,同CSS動畫一樣,甚至可以使用一些賽貝爾曲線,例如cubic-bezier(0.4, 0, 0.2, 1)。我們可以在這兩個網站自定義挑選賽貝爾曲線的表達式:

    同CSS一樣,并不是所有的賽貝爾曲線都能被使用的,所以關鍵幀的設置必不可少,它在Angular中是這樣寫的:

    transition('* => void', [
      animate(300, keyframes([
        style({
            opacity: 1, 
            transform: 'translateX(0)',     
            offset: 0
        }),
        style({
            opacity: 1, 
            transform: 'translateX(-15px)', 
            offset: 0.7
        }),
        style({
            opacity: 0, 
            transform: 'translateX(100%)',  
            offset: 1.0
        })
      ]))
    ])

    上述代碼是一個典型的“離場動畫”,它在第二幀定義了一些“反彈”效果。

    offset屬性定義了此幀在整個動畫中處于哪個時間點,它并不一定用絕對數字定義,而是在0到1之間的相對值(百分比),而且它是可選的,如果省略它,偏移量會自動根據幀數平均分布出來。

    第三方動畫庫

    上述的動畫我們直接寫在了組件中,更多時候往往需要把它們抽象出來,形成一個自己的動畫庫,可以在各個組件調用。下面這個簡單的庫來自于segmentfault社區:

    // animate.ts
    import { 
        trigger, 
        state, 
        style, 
        transition, 
        animate, 
        keyframes 
    } from '@angular/animations';
    
    // 動畫時間線
    var time = '300ms'
    var styles = {
      ease: time + ' ease ',
      linear: time + ' linear ',
      easeIn: time + ' ease-in',
      easeOut: time + ' ease-out',
      stepStart: time + ' step-start',
      stepEnd: time + ' step-end',
      easeInOut: time + ' ease-in-out',
      faseOutSlowIn: time + ' cubic-bezier(0.4, 0, 0.2, 1)',
      inOutBack: time + ' cubic-bezier(0.68, -0.55, 0.27, 1.55)',
      inOutCubic: time + ' cubic-bezier(0.65, 0.05, 0.36, 1)',
      inOutQuadratic: time + ' cubic-bezier(0.46, 0.03, 0.52, 0.96)',
      inOutSine: time + ' cubic-bezier(0.45, 0.05, 0.55, 0.95)'
    }
    
    // 動畫配置
    
    var opts = {
      fadeIn: [
        style({ opacity: 0 }),
        animate(styles.inOutBack, style({ opacity: 1 })),
      ],
      fadeOut: [
        style({ opacity: 1 }),
        animate(styles.inOutBack, style({ opacity: 0 }))
      ],
      shrink: [
        style({ height: '*' }),
        animate(styles.inOutBack, style({ height: 0 }))
      ],
      stretch: [
        style({ height: '0' }),
        animate(styles.inOutBack, style({ height: '*' }))
      ],
      flyIn: [
        style({ transform: 'translateX(-100%)' }),
        animate(styles.inOutBack, style({ transform: '*' }))
      ],
      flyOut: [
        style({ transform: '*' }),
        animate(styles.inOutBack, style({ transform: 'translateX(-100%)' }))
      ],
      zoomIn: [
        style({ transform: 'scale(.5)' }),
        animate(styles.inOutBack, style({ transform: '*' }))
      ],
      zoomOut: [
        style({ transform: '*' }),
        animate(styles.inOutBack, style({ transform: 'scale(.5)' }))
      ]
    }
    
    // 導出動畫時間線定義,供自定義動畫的時候使用
    export const animStyle = styles
    
    // 導出動畫
    export const fadeIn = [trigger('fadeIn', [transition('void => *', opts.fadeIn)])]
    export const fadeOut = [trigger('fadeOut', [transition('* => void', opts.fadeOut)])]
    export const stretch = [trigger('stretch', [transition('void => *', opts.stretch)])]
    export const shrink = [trigger('shrink', [transition('* => void', opts.shrink)])]
    export const flyIn = [trigger('flyIn', [transition('void => *', opts.flyIn)])]
    export const flyOut = [trigger('flyOut', [transition('* => void', opts.flyOut)])]
    export const zoomIn = [trigger('zoomIn', [transition('void => *', opts.zoomIn)])]
    export const zoomOut = [trigger('zoomOut', [transition('* => void', opts.zoomOut)])]
    
    export const simAnim = [
      trigger('simAnim', [
        transition('* => fadeIn', opts.fadeIn),
        transition('* => fadeIn', opts.fadeOut),
        transition('* => shrink', opts.shrink),
        transition('* => stretch', opts.stretch),
        transition('* => flyIn', opts.flyIn),
        transition('* => flyOut', opts.flyOut),
        transition('* => zoomIn', opts.zoomIn),
        transition('* => zoomOut', opts.zoomOut)
      ])
    ]

    上述代碼定義了8種常用動畫效果,還可以自定義time變量修改動畫速度。在使用時,可以在組件直接全部引入:

    import { simAnim } from './animate.ts';

    亦或是單獨引入某個動畫:

    import { fadeIn } from './animate.ts';

    然后在組件元數據中加入動畫數組:

    @Component({
       // ...
       animations: [simAnim]
    })

    然后在模板中加入:<div @flyIn @flyOut>...</div>,也可以寫成<div [@simAnim]="'flyIn'">...</div>

    如果上述代碼仍不滿足需求,可以引入其它開源項目,比如:https://github.com/jiayihu/ng-animate
    它是一個更強大的開源項目,動畫演示及說明文檔非常詳細,這里就不再贅述。

    參考資料

    版權聲明:本文為suzichenaa原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/suzichenaa/article/details/78962374

    智能推薦

    QML進階教程:三、動畫分組(Grouped Animations)

    前言: 如果想同時運行幾個動畫并把他們連接起來,或者在一個一個的運行,或者在兩個動畫之間執行一個腳本。動畫分組 提供了很好的幫助,有兩種方法來分組:平行與連續。可以使用SequentialAnimation(連續動畫) 和ParallelAnimation(平行動畫) 來實現它們,它們作為動畫的容器來包含其它的動畫元素。 代碼實例: 運行軌跡:...

    [Animations] 快速上手 iOS10 屬性動畫

    概述 今天要說的UIViewPropertyAnimator, 是iOS10新的API 詳細 代碼下載:http://www.demodashi.com/demo/10639.html 基礎動畫, 核心動畫到自定義轉場動畫其實都不是什么新東西了, 所以我也是草草看一遍就能夠讀個大概, 但今天要說的UIViewPropertyAnimator, 是iOS10新的API, 其他的好處我還不太清楚, 但...

    Animations開源動效分析(一)POP按鈕動畫

    最近Github有一個上很火的開源動畫集叫Animations。 我也很喜歡做動畫動效,特來學習觀摩。因為動效的特殊性,很多情況下這個項目里的動效不能直接Copy到我們現有的項目中直接使用,所以搞清楚她們的實現原理就很有必要了。建議配合源碼學習。 POP按鈕動畫 沒用過的POP的請移步Facebook Pop 使用指南 效果如下 思路 整體效果是用三個CAShapeLayer和一個UILabel組...

    Animations開源動效分析(二)POP-Stroke動畫

    本教程源碼Animations 作者 YouXianMing,建議配合源碼項目食用 Facebook pop動畫框架簡易教程請移步 Facebook Pop 使用指南 CoreAnimation不簡易教程 如果不想看第三條的教程,也要弄明白CALayer的隱式動畫,否則看本文會疑惑,請移步CALayer的隱式動畫和顯式動畫 CAMediaTimingFunction 今天我們來看一下研究一下CAM...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡