話不多說先看下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的值才能知道延遲時間,所以我上面最後用的是自定義屬性通過延遲添加類來處理延遲動畫,比較好操作。這些便是核心思路。