在可视化页面的设计中,公告滚动组件至关重要。我们要仔细记录它的相关信息,如位于页面何处,外观是怎样的风格,滚动的速度如何,公告内容怎样设置,还有鼠标悬停等交互功能情况,为页面的完善提供精准的数据支撑。 为实现公告滚动效果,直接引入一个三方库不是上上选,自己封装一个组件,在此记录一下。 废话不多说,直接贴代码。
子组件代码:
<template>
<div class="list-scroll-home" ref="box">
<slot></slot>
<!--如果内容不够多,隐藏第二个插槽,同时也无滚动效果-->
<slot v-if="isScroll"></slot>
</div>
</template>
<script>
export default {
name: 'ListScroll',
props: {
// 步长,默认为1
speed: {
default: 1,
type: Number
},
// 数据数组长度,默认为0
dataListHeight: {
default: 0,
type: Number
}
},
data() {
return {
height: 0,
// 是否开启滚动效果
isScroll: true
}
},
watch: {
// 监听数据变化,
dataListHeight: {
handler(val) {
this.isScroll = true
// 当数据发生变换后,等待新的dom及slot都被渲染出来,在进行后续判断
this.$nextTick(() => {
// 在盒子内容高度小于可视高度时不滚动
if (this.boxHeight < this.slot0.clientHeight) {
this.start(this.height)
this.setEvet()
} else {
this.isScroll = false
}
})
},
// 该回调将会在侦听开始之后被立即调用
immediate: true
}
},
computed: {
slot0() {
return this.$refs.box.children[0]
},
slot1() {
return this.$refs.box.children[1]
},
// 盒子的可视高度
boxHeight() {
return this.$refs.box.clientHeight
}
},
methods: {
// 鼠标移入停止滚动 移出继续滚动
setEvet() {
// 移入
this.$refs.box.onmouseenter = () => {
this.isScroll = false
}
// 移出
this.$refs.box.onmouseleave = () => {
this.isScroll = true
this.$nextTick(() => {
this.start(this.height)
})
}
},
// 滚动方法
start(height) {
this.slot0.style = `transform:translateY(-${height}px);`
this.slot1.style = `height:${this.boxHeight}px;transform:translateY(-${height}px);overflow:hidden;`
if (height >= this.slot0.clientHeight) {
this.height = 0
} else {
this.height += this.speed
}
if (!this.isScroll) return
// 执行频率与屏幕刷新率有关系,
// window.requestAnimationFrame() 方法会告诉浏览器你希望执行一个动画。它要求浏览器在下一次重绘之前,调用用户提供的回调函数。
window.requestAnimationFrame(() => {
this.start(this.height)
})
}
}
}
</script>
<style scoped lang="scss">
.list-scroll-home {
overflow: hidden;
}
</style>
组件应用:
<template>
<div class="notice-body">
<!--添加scroll-box类名,限定滚动区域宽高-->
<list-scroll class="scroll-box" :speed="0.5" :data-list-height="noticeList.length">
<!--插槽内容的宽高,会影响滚动区域,高度比scroll-box高的话,会启动滚动效果-->
<div class="notice-body-card" ref="noticeCard">
<div class="notice-one" v-for="(item, index) in noticeList" :key="index">{{ item }}</div>
</div>
</list-scroll>
</div>
</template>
<script>
import ListScroll from './listScroll'
export default {
components: {
ListScroll
},
data() {
return {
noticeList: []
}
},
created() {
this.initData()
},
methods: {
initData() {
// 模拟异步请求数据
setTimeout(() => {
this.noticeList = [
'aaaaaaaaaaaaaaaaaaaaaaaaa',
'bbbbbbbbbbbbbbbbbbbbbbbbb',
'ccccccccccccccccccccccccc',
'ddddddddddddddddddddddddd',
'eeeeeeeeeeeeeeeeeeeeeeeee',
'fffffffffffffffffffffffff'
]
})
}
}
}
</script>
<style scoped lang="scss">
.notice-body {
margin: 28px 24px 10px;
height: calc(100% - 54px);
overflow: hidden;
.scroll-box {
height: 132px;
}
.notice-body-card {
max-height: 390px;
width: 100%;
overflow: hidden;
margin-bottom: 2px;
.notice-one {
width: 100%;
height: 24px;
line-height: 24px;
margin-bottom: 2;
font-size: 12px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
</style>