最近作活動須要作跑馬燈效果,其餘同事也有實現,原本打算複製他們代碼,發現都是使用setInterval
實現了,也沒有封裝爲組件,因此本身用CSS3
實現了一下跑馬燈效果,並封裝爲組件,這樣之後在須要寫的時候,只須要引入組件就能夠了。css
HTML
結構父盒子固定,子盒子移動,幷包含須要效果的內容CSS3
實現確定須要 infinite
(循環執行動畫)wrapWidth
),還有子盒子的總寬度(offsetWidth
)CSS3
動畫須要的時間duration
向外暴露三個參數vue
github 地址源碼地址css3
源碼中大部分都添加了註釋,若有問題請指出謝謝git
<template>
<div ref="wrap" class="wrap">
<div ref="content" class="content" :class="animationClass" :style="contentStyle" @animationend="onAnimationEnd" @webkitAnimationEnd="onAnimationEnd">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: {
content: {
default: ''
},
delay: {
type: Number,
default: 0.5
},
speed: {
type: Number,
default: 100
}
},
mounted() {},
data() {
return {
wrapWidth: 0, //父盒子寬度
firstRound: true, //判斷是否
duration: 0, //css3一次動畫須要的時間
offsetWidth: 0, //子盒子的寬度
animationClass: '' //添加animate動畫
};
},
computed: {
contentStyle() {
return {
//第一次從頭開始,第二次動畫的時候須要從最右邊出來因此寬度須要多出父盒子的寬度
paddingLeft: (this.firstRound ? 0 : this.wrapWidth) + 'px',
//只有第一次的時候須要延遲
animationDelay: (this.firstRound ? this.delay : 0) + 's',
animationDuration: this.duration + 's'
};
}
},
watch: {
content: {
//監聽到有內容,從後臺獲取到數據了,開始計算寬度,並計算時間,添加動畫
handler() {
this.$nextTick(() => {
const { wrap, content } = this.$refs;
const wrapWidth = wrap.getBoundingClientRect().width;
const offsetWidth = content.getBoundingClientRect().width;
this.wrapWidth = wrapWidth;
this.offsetWidth = offsetWidth;
this.duration = offsetWidth / this.speed;
this.animationClass = 'animate';
});
}
}
},
methods: {
//這個函數是第一次動畫結束的時候,第一次沒有使用infinite,第一次動畫執行完成後開始使用添加animate-infinite動畫
onAnimationEnd() {
this.firstRound = false;
//這是時候樣式多出了padding-left:this.wrapWidth;因此要想速度同樣須要從新計算時間
this.duration = (this.offsetWidth + this.wrapWidth) / this.speed;
this.animationClass = 'animate-infinite';
}
}
};
</script>
<style scoped>
.wrap {
width: 100%;
height: 24px;
overflow: hidden;
position: relative;
background: rgba(211, 125, 066, 1);
position: relative;
padding: 0;
}
.wrap .content {
position: absolute;
white-space: nowrap;
}
.animate {
animation: paomadeng linear;
}
.animate-infinite {
animation: paomadeng-infinite linear infinite;
}
@keyframes paomadeng {
to {
transform: translate3d(-100%, 0, 0);
}
}
@keyframes paomadeng-infinite {
to {
transform: translate3d(-100%, 0, 0);
}
}
</style>
複製代碼
請參考個人另一篇文章,如何將本身的 vue 組件發佈爲 npm 包github
npm install heyushuo-marquee --save
import PaoMaDeng from 'heyushuo-marquee';
<PaoMaDeng :delay="0.5" :speed="100" :content="arr"> <span v-for="(item, index) in arr" :key="index">{{item}}</span> </PaoMaDeng>
複製代碼