一、前言
在日常开发中会接触到可视化大屏展示的功能页面,而这些界面主要应用与制造业、工厂设备电子屏幕上。涉及到表格数据量大,这个时候为了方便展示避免用户手动查看,就需要设置表格滚动展示数据。
二、实现原理
要想实现表格数据滚动,我们先来一步步解析需要做哪些准备。
2.1 明确最终效果
- 表头标题数据固定
- 列表数据超出固定高度后滚动
- 滚动要丝滑避免卡顿
2.2 实现思路
- 首先设置一个顶层容器包裹表格数据,设置固定高度,并设置溢出隐藏;
- 这样滚动数据超出就不会在界面上显示出来;
- 将表头thead固定,设置相对定位提升层级;
- 滚动表格主体tbody;
- 滚动高度就为tbody的实际高度,当超过顶层容器时便可以滚动;
2.3 图例展示
简单画了一个草图来描述需要实现的效果,主要思想就是顶层容器固定高度设置溢出隐藏,这样主体内容滚动溢出后不展示;从而实现视觉上的滚动列表。
三、模拟代码界面代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./jquery.min.js"></script>
<title>CSS实现滚动</title>
<style>
* {
padding: 0;
margin: 0;
}
body {
background-color: rgb(17, 34, 67);
color: white;
padding-top: 40px;
}
th,
td {
border: 1px solid white;
padding: 12px 0;
background: rgb(17, 34, 67);
}
.table_box {
width: 80vw;
height: 80vh;
margin: auto;
text-align: center;
overflow: hidden;
}
thead {
position: relative;
z-index: 2;
background: red;
}
</style>
</head>
<body>
<div class="table_box">
<table id="table" cellspacing="0" width="100%">
<thead>
<tr>
<th style="width: 20%">工单</th>
<th style="width: 20%">物料</th>
<th style="width: 10%">数量</th>
<th style="width: 10%">单位</th>
<th style="width: 30%">地址</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script>
// 随机数
const setRandomNum = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 渲染表格
const renderTable = (res) => {
const tbodyDom = document.getElementById('scroll_table');
let str = '';
res.forEach((item) => {
str += `
<tr>
<td style="width: 20%">${item.workNum}</td>
<td style="width: 20%">${item.meatailNum}</td>
<td style="width: 10%">${item.qty}</td>
<td style="width: 10%">${item.uom}</td>
<td style="width: 30%">${item.addr}</td>
</tr>
`;
});
// tbodyDom.innerHTML = str;
document.querySelector('#table tbody').innerHTML = str;
animation();
// tableScrollRender();
}
// 界面初始化
const hanleInit = () => {
const result = [];
let workNum = 20240227001;
let meatailNum = 100001;
const addr = ["西安", "上海", "北京", "深圳", "杭州", "成都", "重庆", "海门", "福建", "香港", "安康", "西藏"];
for (let i = 0; i < 15; i++) {
result.push({
workNum: workNum++,
meatailNum: meatailNum++,
qty: setRandomNum(10, 1000),
uom: 'KG',
addr: addr[setRandomNum(0, 11)],
});
}
renderTable(result);
};
hanleInit();
</script>
</body>
</html>
上方代码是我简单搭建的静态表格数据,并没有设置滚动;避免重复粘贴界面,所以统一就把默认界面代码放到了这里。下面会介绍几种滚动实现方式。
四、具体实现的几种方式
实现滚动的核心思想:就是将表格主体tbody上下缓慢移动来实现;
移动的方式:
- 定位修改top移动;
- 设置transform中的translateY移动;
- css3动画实现移动
4.1 通过js修改tbody的translateY偏移量实现
不管是定位还是translateY原理都是一样,这里我们直接用translateY;
封装滚动js:
/**
* @description 表格滚动方法封装
* @param id 滚动表格的id名(必须是唯一值,默认值table)
* @param setp 每次向上滚动距离长度(默认值2)
* @param time 每次移动的时间间隔(默认值100,单位毫秒)
* @mark 包裹表格的标签元素必须要设置高度并且设置overflow: hidden
*/
function tableScrollRender(id = 'table', setp = 2, time = 100) {
// 获取需要滚动的表格元素
var $tableDom = $(`#${id}`);
// 定时器id
var timerId = null;
// 向上偏移长度
var translateY = 0;
// 没有找到表格元素/表格主体内容高度过小取消滚动
if (!$tableDom.length || $tableDom.outerHeight() < $tableDom.parent().outerHeight()) {
return;
};
// 获取表格内容主体
var tBody = $(`#${id} tbody`);
// 获取表格主体高度
var offsetHeight = tBody.outerHeight();
// 固定表头
var thead = $(`#${id} thead`);
if (thead.length) {
thead.css({
position: 'relative',
zIndex: 99,
});
// 滚动函数
function srcollFn() {
clearTimeout(timerId);
translateY += setp;
if (translateY >= offsetHeight) {
translateY = 0;
}
// 设置列表数据向上偏移
tBody.css({
'transform': `translateY(-${translateY }px)`,
});
timerId = setTimeout(srcollFn, time);
};
timerId = setTimeout(srcollFn, time
// hover时停止滚动
$(`#${id}`).find('tbody').hover(function() {
clearTimeout(timerId);
}, function() {
timerId = setTimeout(srcollFn, time);
})
}
上方方法直接使用即可;
4.2 通过css3中的animation动画属性来实现移动
这种方案相对简单不需要使用定时器来逐帧更改偏移量滚动,只需要计算完成一次滚动所需时间设置即可;
首先设置滚动css属性:
/* 鼠标移入滚动区域变成手型 */
#table:hover tbody {
cursor: pointer;
}
/* 鼠标移入滚动区域暂停动画 */
#table.pause tbody {
animation-play-state: paused !important;
}
/* 动画关键帧 */
@keyframes cl-scrolling {
from {
transform: translate(0px, 0%);
to {
transform: translate(0px, -100%);
}
}
渲染完表格数据后,获取主体高度计算所需时间。
封装js函数:
/**
* @description 表格滚动方法封装
* @param id 滚动表格的id名(必须是唯一值,默认值table)
* @mark 包裹表格的标签元素必须要设置高度并且设置overflow: hidden
*/
function animation(id = 'table') {
// 限制每个容器的高度
let seamless_sub = document.querySelector(`#${id} tbody`);
if (seamless_sub.clientHeight > document.querySelector(`.table_box`).clientHeight) {
// 调节滚动速率,使滚动速率不至于过快或过慢
let scroll_speed = Math.max(4, Math.ceil(seamless_sub.clientHeight / 35));
seamless_sub.style = "animation: cl-scrolling " + scroll_speed + "s infinite linear";
}
// 监听鼠标移入事件,暂停动画; 同时鼠标移出,继续动画
seamless_sub.addEventListener("mouseenter", function(event) {
event.target.classList.add("pause"
});
seamless_sub.addEventListener("mouseleave", function(event) {
event.target.classList.remove("pause");
})
}
4.3 滚动插件库
上方两种方案属于可以用于项目中少了滚动需求。
当项目中很多地方都需要大屏滚动的需求时;这个时候就需要使用第三方插件库,有更多炫酷的展示。
这里简单介绍几种滚动插件:
- DataV:对于vue与react都有相关的插件;
- vue-seamless-scroll:基于vue的无缝滚动组件
- react-window:基于React的无缝滚动组件