Commit e38ef0d5 authored by 周宏民's avatar 周宏民

feat: 数据滚动组件

parent fa6ad83a
......@@ -104,6 +104,7 @@ export default {
'SelectCustom',
'TreeCustom',
'AlarmScrollAssembly',
'DataCarousel',
],
},
{
......
......@@ -326,6 +326,18 @@
"limit": "2 s",
"webpack": false,
"running": false
},
{
"path": "packages/base-components/DataCarousel/lib/**/*.js",
"limit": "2 s",
"webpack": false,
"running": false
},
{
"path": "packages/base-components/DataCarousel/es/**/*.js",
"limit": "2 s",
"webpack": false,
"running": false
}
],
"name": "wisdom-components"
......
<!--
* @Title:
* @Author: hongmye
* @Date: 2023-02-08 16:03:42
-->
# Change Log
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<!--
* @Title:
* @Author: hongmye
* @Date: 2023-02-08 16:03:42
-->
# `@wisdom-components/dataCarousel`
> TODO: description
## Usage
```
const empty = require('@wisdom-components/dataCarousel');
// TODO: DEMONSTRATE API
```
{
"name": "@wisdom-components/dataCarousel",
"version": "0.1",
"description": "@wisdom-components/dataCarousel",
"author": "hongmin",
"homepage": "",
"license": "ISC",
"sideEffects": [
"*.less"
],
"module": "es/index.js",
"main": "lib/index.js",
"files": [
"lib",
"es",
"dist"
],
"directories": {
"lib": "lib",
"es": "es",
"dist": "dist",
"test": "__tests__"
},
"publishConfig": {
"registry": "https://g.civnet.cn:4873/"
},
"repository": {
"type": "git",
"url": "https://g.civnet.cn:8443/ReactWeb5/wisdom-components.git"
},
"dependencies": {
"@babel/runtime": "^7.17.9",
"classnames": "^2.2.6",
"swiper": "^6.8.1"
}
}
\ No newline at end of file
---
title: DataCarousel - 数据轮播
nav:
title: 基础组件
path: /components
group:
path: /
---
# DataCarousel 数据滚动
列表数据多行轮播滚动,会跟据容器高度和行高及间隔计算每页最大数量。鼠标悬浮停止轮播
## 代码演示
<code src="./demos/Basic.tsx">
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| renderItem | 自定义渲染每项内容(必传) | ReactNode | - |
| itemHeight | 每行行高, | number | 40 |
| list | 数据源 | array | [] |
| gap | 每项间隔(每页最后一项没有) | array | [] |
| renderGap | 自定义间隔样式 | ReactNode | null |
| autoplay | 轮播时间,单位ms,传0则不轮播 | number | 3000 |
| config | swiper参数 | object | {} |
\ No newline at end of file
/*
* @Title:
* @Author: hongmye
* @Date: 2023-02-08 16:03:42
*/
import { Button } from 'antd';
import DataCarousel from '../index';
import React from 'react';
import styles from './index.less';
function Demo() {
const list = [
{ userId: '大邑小区', userName: '0.4Mpa' },
{ userId: '工业园一', userName: '0.4Mpa' },
{ userId: '工业园二', userName: '0.4Mpa' },
{ userId: '工业园三', userName: '0.4Mpa' },
{ userId: '工业园四', userName: '0.4Mpa' },
{ userId: '工业园五', userName: '0.4Mpa' },
{ userId: '工业园六', userName: '0.4Mpa' },
{ userId: '工业园七', userName: '0.4Mpa' },
{ userId: '工业园八', userName: '0.4Mpa' },
];
const renderItem = (item) => {
return (
<div className={styles.list_item}>
<span>{item.userId}</span>
<span>{item.userName}</span>
</div>
);
};
return (
<div style={{ width: '100%' }}>
<div style={{ width: '300px', height: '200px', background: 'rgba(0,0,0,0.2)' }}>
<DataCarousel list={list} renderItem={renderItem}></DataCarousel>
</div>
<br />
</div>
);
}
export default Demo;
.list_item {
height: 40px;
line-height: 1;
background: rgba(255, 0, 0, 0.5);
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 0 10px;
}
\ No newline at end of file
/*
* @Title:数据列表轮播组件
* @Author: hongmye
* @Date: 2023-02-08 16:03:42
*/
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react';
import 'swiper/components/navigation/navigation.min.css';
import 'swiper/components/pagination/pagination.min.css';
import SwiperCore, { Autoplay, Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/swiper.min.css';
import styles from './index.less';
SwiperCore.use([Autoplay, Pagination, Navigation]);
const DataCarousel = ({ list, itemHeight, gap, renderItem, renderGap, config, autoplay }) => {
const contentRef = useRef(null);
const [colNum, setColNum] = useState(0);
const [listData, setListData] = useState([]);
const [height, setHeight] = useState('100%');
const spliceArr = (arr, num) => {
let reArr = [];
arr.map((item) => {
if (!reArr[reArr.length - 1] || reArr[reArr.length - 1].length === num) {
// 新行添加
reArr.push([]);
}
if (reArr[reArr.length - 1].length !== num) {
// 长度不够则直接添加
reArr[reArr.length - 1].push(item);
}
return null;
});
return reArr;
};
useEffect(() => {
if (contentRef.current) {
// 计算每页能显示多少行数据
const _Height = contentRef.current.offsetHeight;
const item_height = itemHeight + gap;
const num = Math.floor((_Height + gap) / item_height);
setHeight(item_height * (num - 1) + itemHeight);
setColNum(num || 1);
}
}, [contentRef.current?.offsetHeight, itemHeight, gap]);
useEffect(() => {
if (colNum) {
setListData(spliceArr(list, colNum) || []);
}
}, [list, colNum]);
return (
<div
className={classNames(styles.dataCarousel, 'dataCarousel')}
style={{ width: '100%', height: '100%' }}
ref={contentRef}
>
<div
className={classNames(styles.dataCarouselSwiper)}
style={{ width: '100%', height: height }}
>
{listData && listData.length ? (
<Swiper
slidesPerView={1}
autoplay={
autoplay
? {
delay: listData.length > 1 ? autoplay : false,
disableOnInteraction: false,
}
: false
}
height={height}
loop
direction="vertical"
onSlideChange={(e) => {}}
onSwiper={(swiper) => {
//鼠标悬浮暂停效果
swiper.$el[0].addEventListener('mouseover', () => swiper.autoplay.stop());
//鼠标移开后继续自动滚屏效果
swiper.$el[0].addEventListener('mouseleave', () => {
listData.length > 1 ? swiper.autoplay.start() : '';
});
}}
{...config}
>
{listData.map((item, index) => (
<SwiperSlide key={index} virtualIndex={index} onClick={() => {}}>
{item.map((i, iIndex) => (
<div key={iIndex}>
{renderItem(i, index * colNum + iIndex)}
{colNum - 1 > iIndex ? (
renderGap ? (
renderGap()
) : (
<div style={{ height: gap }}></div>
)
) : null}
</div>
))}
</SwiperSlide>
))}
</Swiper>
) : null}
</div>
</div>
);
};
DataCarousel.defaultProps = {
itemHeight: 40,
gap: 10,
renderItem: () => {},
renderGap: null,
list: [],
config: {}, // swiper参数
autoplay: 3000,
};
DataCarousel.propTypes = {
itemHeight: PropTypes.number,
gap: PropTypes.number,
renderItem: PropTypes.func,
renderGap: PropTypes.func,
list: PropTypes.array,
config: PropTypes.object,
autoplay: PropTypes.number,
};
export default DataCarousel;
@root-entry-name: 'default';
@import '~antd/es/style/themes/index.less';
.dataCarousel {
width: 100%;
height: 100%;
overflow-y: auto;
.dataCarouselSwiper {
overflow-y: auto;
}
}
.dataCarousel {
:global {
.swiper-container {
height: 100%;
width: 100%;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment