表格无缝滚动
动态列表格无缝滚动
-
实现效果
- 无缝滚动
- 支持自定义传入样式
- 支持label对象取对象里属性(bind)
- 支持鼠标移入暂停,移出继续滚动
-
实现思路
通过定时器向上移动。当需要滚动时,定义两个ref,内容一样,第一个滚动完,第二个接上去实现无缝滚动(思路同轮播图)。 -
使用示例
普通表格示例
对后端返回的tableData简单处理一下,状态的字段加逻辑变个颜色
动态列使用示例
效果,日期列是动态列
-
公共组件滚动表格代码实现
/*
* @Descripttion: 看板滚动表格组件
* @Author: 小雨滴 <xuyuFighting@163.com>
* @Date: 2023-09-12 15:07:21
* @LastEditTime: 2024-05-22 10:40:27
*/
import React, { useRef, useEffect, useState } from 'react';
import style from './scroll.less';
interface Column {
label: string | object;
name: string;
suffix?: string; // 后缀
color?: string; // 整列颜色
bind?: string; // label是一个对象时,区对象的哪个属性展示
}
interface ScrollTableProps {
tableData: any[];
columnData: Column[];
lineOverWrap?: boolean; // 行溢出是否换行展示,默认不换行...展示
tableLineStyle?: {}; // 表格高度,字体大小等样式
tableHeadStyle?: {}; // 表格头样式
colorField?: string; // 单元格变色处理,此时要传入对应的color才生效
color?: string // 单元格颜色
}
export default function ScrollTable(props: ScrollTableProps) {
const {
tableData = [],
columnData = [],
tableLineStyle = {},
tableHeadStyle = {},
lineOverWrap = false,
} = props;
const warper = useRef<any>(null);
const ones = useRef<any>(null);
const twos = useRef<any>(null);
const [isScrolle, setIsScrolle] = useState(true);
useEffect(() => {
let timer;
if (isScrolle) {
if (warper.current.offsetHeight <= ones.current.offsetHeight) {
twos.current.innerHTML = ones.current.innerHTML;
}
timer = setInterval(() => {
if (warper.current.scrollTop >= ones.current.scrollHeight) {
warper.current.scrollTop = 0;
} else {
warper.current.scrollTop++;
}
}, 100);
}
return () => {
clearTimeout(timer);
};
}, [isScrolle, tableData.length]);
const handleMouseOver = () => {
setIsScrolle(false);
};
const handleMouseLeave = () => {
setIsScrolle(true);
};
const getFontColorStyle = (col, item) => {
const fontStyle = {
color: 'inherit',
};
if (!item.colorField) {
fontStyle.color = col.color || 'inherit';
} else if (col.name === item.colorField) {
fontStyle.color = item.color || 'inherit';
}
return fontStyle;
};
return (
<div
className={style['my-content-center']}
onMouseOver={handleMouseOver}
onMouseLeave={handleMouseLeave}
onFocus={() => {}}
>
<div className={style['my-content-center-table-header']} style={tableHeadStyle}>
{columnData.map((item: any) => {
return (
<div
key={item.name}
className={`${style['column-head']} ${style['column-week']}`}
title={item.label}
>
<div>{item.label}</div>
</div>
);
})}
</div>
<div ref={warper} className={style['my-content-center-content']}>
<div ref={ones} className={style['my-content-center-table-content']}>
{tableData.length
? tableData.map((item: any, index: number) => {
return (
<div
className={
lineOverWrap
? style['my-content-center-table-content-wrap']
: style['my-content-center-table-content-item']
}
key={String(index)}
style={tableLineStyle}
>
{columnData.map((val: Column, i: number) => {
return (
<div
key={String(i)}
// className={style['my-content-center-table-content-item-item']}
className={
lineOverWrap
? style['my-content-center-table-content-wrap-item']
: style['my-content-center-table-content-item-item']
}
style={getFontColorStyle(val, item)}
title={`${val.bind ? item[val.name][val.bind] : item[val.name]} ${
val.suffix || ''
}`}
>
{val.bind ? item[val.name][val.bind] : item[val.name]}
{val.suffix || ''}
</div>
);
})}
</div>
);
})
: null}
</div>
{tableData.length ? (
<div ref={twos} className={style['my-content-center-table-content']} />
) : null}
</div>
</div>
);
}
less代码如下
/*
* @Descripttion: 看板滚动表格组件
* @Author: 小雨滴 <xuyuFighting@163.com>
* @Date: 2023-09-12 15:07:21
* @LastEditTime: 2024-05-22 10:40:27
*/
.my-content-center {
width: 100%;
height: 100%;
margin-bottom: 30px;
color: #fff;
font-size: 16px;
&-table-header {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
height: 50px;
line-height: 50px;
background: rgba(130, 254, 255, 0.25);
.column-head {
flex: 1;
overflow: hidden;
color: #00ffd8;
white-space: nowrap;
text-align: center;
text-overflow: ellipsis;
}
}
&-content {
height: calc(100% - 50px);
overflow: hidden;
}
&-table-content {
width: 100%;
overflow: auto;
&-item {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
height: 50px;
overflow: hidden;
line-height: 50px;
&:nth-of-type(even) {
// background: #0E2B2F;
background: rgba(130, 254, 255, 0.08);
}
&-item {
flex: 1;
height: 100%;
overflow: hidden;
white-space: nowrap;
text-align: center;
text-overflow: ellipsis;
}
}
&-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
width: 100%;
min-height: 50px;
overflow: hidden;
&:nth-of-type(even) {
// background: #0E2B2F;
background: rgba(130, 254, 255, 0.08);
}
&-item {
flex: 1;
height: 100%;
text-align: center;
}
}
}
}