vue中結合animate.css實現元素動畫入場
阿新 • • 發佈:2019-02-20
話不多說先看下demo的GIF:
1.首先引入animate.css,可以直接在index.html中cdn引入; 2.其次在開發這種動畫較多的頁面我覺得還是引用jquery比較方便,操作dom稍多, 我這裡沒有使用jquery,就想複習複習原生js。可以npm安裝,在build/webpack.base.conf.js中定義外掛: var webpack = require('webpack '); 在module.exports的物件中加入: plugins:[ new webpack.ProvidePlugin({ $:"jquery", jQuery:"jquery", "windows.jQuery":"jquery" }) ],
接下來直接上該頁面程式碼,就是一個vue元件:
<template> <div class="home"> <div class="header " id="header" :class="{fixed: isFixed}"> <div class=" fixed-width clearfix"> <div class="header-title fl">我是頂部</div> <div class="header-buy fr" >我也是頂部</div> </div> </div> <div class="content"> <div class="banner"></div> <div class="animate-box slide"> <h2 class="animate text-h2" data-ani="fadeInUpBig">LuckLin520 Written in Chengdu</h2> <p class="animate text-p" data-ani="rollIn" data-delay="1000">Thank you for reading and I will continue to work hard! —————2018/08/08</p> </div> <div class="animate-box bounce"> <div class="animate yellow" data-ani="bounceInLeft"></div> <div class="animate red" data-ani="bounceInRight"></div> <div class="animate green" data-ani="bounceInLeft"></div> <div class="animate blue" data-ani="bounceInRight"></div> </div> <div class="animate-box slide"> <h2 class="animate text-h2" data-ani="fadeInUpBig">做真實的自己,一切都會好起來的</h2> <p class="animate text-p" data-ani="slideInRight" data-delay="1000">Be true to yourself and everything will be fine</p> </div> <div class="animate-box zoom"> <div class="animate one" data-ani="bounceInLeft"></div> <div class="animate two" data-ani="bounceInRight"></div> <div class="animate three" data-ani="bounceInLeft"></div> <div class="animate four" data-ani="bounceInRight"></div> </div> </div> </div> </template> <script> export default { data () { return { isFixed: 0 } }, methods: { handleScroll() { let top = pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; if(top > 250){ this.isFixed = 1; }else if(top < 200){ this.isFixed = 0; } }, handleAnimate() { let top = pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; let vh = document.documentElement.clientHeight; let dom = document.querySelectorAll(".animate"); [].slice.call(dom).forEach(v => { if(top + vh > v.offsetTop){ var delay = v.dataset.delay; if(delay){ setTimeout(() => { v.style.opacity = 1; v.classList.add(v.dataset.ani) }, delay) }else{ v.style.opacity = 1; v.classList.add(v.dataset.ani) } }else{ v.classList.remove(v.dataset.ani) v.style.opacity = 0; } }) } }, mounted() { this.$nextTick(() => { this.handleAnimate()//初始化第一次載入時在視口內就執行動畫 addEventListener('scroll', this.handleScroll); addEventListener('scroll', this.handleAnimate); }) }, destroyed() { removeEventListener('scroll', this.handleScroll);//避免影響其他頁面 removeEventListener('scroll', this.handleAnimate); } } </script> <style scoped lang="scss"> .header{ background: green; height: 50px; } .fixed{ position: fixed; top: 0px; z-index: 4; width: 100%; animation: slideInDown .5s; } .content{ height: 2000px; background: pink; overflow: hidden; .banner{ width: 80%; height: 400px; background:orange; margin: 80px auto; } .slide{ font-size: initial; height: 100px; } .bounce{ width: 80%; margin:0 auto 80px; display: flex; flex-wrap: wrap; justify-content: space-between; &>div{ height: 120px; float: left; width: 45%; } .yellow{ background:yellow; margin-bottom: 40px; } .red{ background:red; } .green{ background:green; } .blue{ background:blue; } } .zoom{ width: 80%; margin:0 auto 80px; display: flex; justify-content: space-between; &>div{ width: 23%; height: 263px; } .one{ background:url(http://www.codingke.com/themes/codingnew-1/img/study/python/python_block1_img1.jpg) no-repeat center/100%; } .two{ background:url(http://www.codingke.com/themes/codingnew-1/img/study/python/python_block1_img2.jpg) no-repeat center/100%; } .three{ background:url(http://www.codingke.com/themes/codingnew-1/img/study/python/python_block1_img3.jpg) no-repeat center/100%; } .four{ background:url(http://www.codingke.com/themes/codingnew-1/img/study/python/python_block1_img4.jpg) no-repeat center/100%; } } } //animate classs .animate{ opacity: 0; } .fadeInUpBig{ animation: fadeInUpBig 1s; } .rollIn{ animation: rollIn 1s; } .slideInRight{ animation: slideInRight 1s; } .bounceInLeft{ animation: bounceInLeft 2s ease-in; } .bounceInRight{ animation: bounceInRight 2s ease-in; } </style>
不難看得出核心程式碼就是那個handleAnimate方法,實際運用中肯定多個頁面會有動畫效果,這個函式可以抽離成公共程式碼,其實他可以只需要接收一個所有運動元素的統一選擇器(這裡的".animate"),而該方法通過這些".animate"元素傳入的自定義屬性ani來判斷該元素被指定了哪種動畫型別,通過動態新增該型別名稱的class來定義animation動畫,在最初我的思路是將animation-delay動畫延遲同樣用該型別的class在css中定義,最後我又考慮到如果不止一個元素必須用同一個動畫型別,但是有的需要有的不需要延遲呢,那不是該屬性出現耦合了?所以最後把所有動畫延遲定義在該元素自身—data-delay,沒錯又是自定義屬性,把需要有延遲時間的元素就加一個自定義屬性delay,執行中判斷是否有該屬性,有的話就用setTimeout來延遲該屬性的值的時間新增動畫class,這樣就讓動畫樣式和動畫延遲互不影響了,動畫型別樣式完全複用,同時,如果直接定義animation-delay或者直接animation以簡寫的形式來定義動畫延遲的話,當被新增上動畫class時該元素就會立馬顯示出來,就是說在延遲期間(元素動起來之前)它也是處於顯示狀態的,可以用js操作用setTimeout來延遲元素顯示出來,不過比較麻煩了,因為還得js獲取animate-delay的值才能知道延遲時間,所以我上面最後用的是自定義屬性通過延遲新增類來處理延遲動畫,比較好操作。這些便是核心思路。