一、div列表滚动
现在需要实现一个效果,内容无限、平滑、无闪动地向上滚动;当鼠标悬停到列表时,滚动暂停并高亮当前项;鼠标移出后继续滚动。这是在大屏项目中经常见到的一种展示数据的方式,本文为具体的实现方式。
实现原理:
在使用了js控制之后发现有闪动的现象,然后就换了种方式,我的想法是:把原始列表渲染两次(A + A),用 CSS @keyframes 把整个双倍内容从 translateY(0) 平滑移动到 translateY(-50%)(即移动一份内容的高度),动画无限循环。因为下半部分是上半部分的复制,循环在视觉上是连续的、无断点的——没有 JS 在中间做“重置”,因此无闪动。话不多说直接上代码
html:
<template>
<div class="scroll-list" @mouseenter="pauseScroll" @mouseleave="resumeScroll">
<div class="scroll-content" ref="scrollContent">
<div
v-for="item in typicalCaseList"
:key="'a' + item.id"
class="scroll-item"
>
<span>{{ item.text }}</span>
</div>
<!-- 复制一份 -->
<div
v-for="item in typicalCaseList"
:key="'b' + item.id"
class="scroll-item"
>
<span>{{ item.text }}</span>
</div>
</div>
</div>
</template>
当上半段滚出视窗时,下半段的内容正好衔接上,使得动画循环时不会出现断裂。注意 key 的不同,避免 Vue 复用 DOM 导致复制失败
js:
<script>
export default {
data() {
return {
typicalCaseList: [
// ... 你的数据
]
};
},
mounted() {
const list = this.$refs.scrollContent;
// 根据列表长度动态设置动画时长(可按需调整策略)
const itemCount = this.typicalCaseList.length;
const duration = Math.max(8, itemCount * 0.8); // 秒,示例:最少 8s
list.style.setProperty('--duration', `${duration}s`);
},
methods: {
pauseScroll() {
this.$refs.scrollContent.style.animationPlayState = 'paused';
},
resumeScroll() {
this.$refs.scrollContent.style.animationPlayState = 'running';
}
}
};
</script>
@mouseenter / @mouseleave 控制动画的播放状态,零延迟暂停/恢复
css:
<style scoped>
.scroll-list {
height: 228px;
margin: 0px 8px;
overflow: hidden;
position: relative;
}
.scroll-content {
display: flex;
flex-direction: column;
animation: scroll-up var(--duration) linear infinite;
}
.scroll-item {
height: 43px;
font-size: 16px;
color: #D0DEEE;
padding: 0 10px;
transition: all 0.3s;
border-bottom: 1px dashed rgba(69,174,253,0.43);
display: flex;
flex-direction: row;
align-items: center;
}
.scroll-item:hover {
color: #03A7FA;
}
/* 真正无缝滚动动画 */
@keyframes scroll-up {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-50%);
}
}
</style>
translateY(-50%):把整个容器往上移 50%(即整份内容的一半),正好把第一份内容滚出,显示第二份(与第一份相同),循环接着第一份。他之所以能解决闪烁的原因是因为动画是连续的无限循环,浏览器合成层平滑过渡,动画结束后 CSS 自动从 0% 开始新一轮,但因为画面内容与起始状态一致,用户看不到跳变(没有 JS 重置 scrollTop 的那一帧)
拓展:
还可以根据需求进行一些部分的拓展,比如
- 动态速度或者是时长更精确的计算
通过计算单个.scroll-item的高度,计算原始列表总高度来获取更准确的值
const itemHeight = this.$refs.scrollContent.querySelector('.scroll-item').offsetHeight;
const H = itemHeight * this.typicalCaseList.length;
const speed = 30; // px/s
const duration = H / speed;
this.$refs.scrollContent.style.setProperty('--duration', `${duration}s`);
- 只在数据高度超出容器时启用滚动
如果列表很短(内容总高度 <= 你设定的总高度),不需要滚动。判断逻辑:
if (content.scrollHeight <= container.clientHeight) {
// 不启用动画:移除 animation
content.style.animation = 'none';
} else {
content.style.animation = `scroll-up var(--duration) linear infinite`;
}
二、table表格滚动
table表格的滚动主要是实现思路为复制一个表格内容,让其形成无缝滚动的感觉,结合css实现效果
<div class="table-scroll-wrapper">
<table class="table-box-right">
<thead>
<tr>
<th>姓名</th>
<th>城市</th>
<th>年龄</th>
</tr>
</thead>
</table>
<div class="table-body-wrapper">
<table class="table-box-right scroll-content">
<!-- 可以通过判断来实现达到多少条数据时,触发滚动动画 -->
<tbody :class="{ scrollable: tableData.length > 5 }">
<!-- 克隆两次实现无缝滚动 -->
<tr v-for="item in tableData" :key="item.f_id">
<td>{{ item.name }}</td>
<td>{{ item.city }}</td>
<td>{{ item.age }}</td>
</tr>
<tr v-for="item in tableData" :key="'clone-' + item.f_id">
<td>{{ item.name }}</td>
<td>{{ item.city }}</td>
<td>{{ item.age }}</td>
</tr>
</tbody>
</table>
</div>
</div>
css部分实现滚动
.table-scroll-wrapper {
width: 100%;
color: #fff;
padding: 20px;
}
.table-box-right {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.table-box-right th,
.table-box-right td {
border: 1px solid #0058af;
text-align: center;
padding: 6px 8px;
font-size: 14px;
}
/* 固定表头 */
.table-box-right thead th {
background: #103e5f;
position: sticky;
top: 0;
z-index: 2;
color: #37eef4;
}
.table-box-right td {
background: #01204c;
}
/* 滚动容器 */
.table-body-wrapper {
max-height: 200px;
overflow: hidden;
position: relative;
}
.scroll-content tr {
display: table; /* 保持表格样式 */
width: 100%;
table-layout: fixed;
}
@keyframes scrollUp {
0% { transform: translateY(0); }
100% { transform: translateY(-50%); } /* 移动一半,实现无缝滚动 */
}
.scroll-content tbody.scrollable {
display: block;
animation: scrollUp 15s linear infinite; // 控制滚动速度 数值越大滚动越慢
}
.table-body-wrapper:hover .scroll-content tbody.scrollable {
animation-play-state: paused;
}
/* 小于X条的 tbody 不加动画,默认不滚动 */
.scroll-content tbody:not(.scrollable) {
display: table-row-group; /* 保持正常表格布局 */
animation: none;
}
上述是通过纯css样式控制当数据大于你规定的条数时,表格开始滚动,鼠标划入停止动画,离开继续动画,控制css属性这样就能简单的实现无缝滚动效果
5577

被折叠的 条评论
为什么被折叠?



