/* * @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, onSwiper, }) => { const contentRef = useRef(null); const swiperRef = 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) { const arr = spliceArr(list, colNum) || []; if (swiperRef.current) { if (arr.length > 1 && autoplay * 1) { swiperRef.current.autoplay.start(); } else { swiperRef.current.autoplay.stop(); } } setListData(arr); } }, [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 * 1 && listData.length > 1 ? { delay: listData.length > 1 ? autoplay : false, disableOnInteraction: false, } : false } height={height + 2} // 加2是解决第二页顶部有少量显示的问题 loop direction="vertical" onSlideChange={(e) => {}} onSwiper={(swiper) => { swiperRef.current = swiper; onSwiper && onSwiper(swiper); //鼠标悬浮暂停效果 swiper.$el[0].addEventListener('mouseover', () => swiper.autoplay.stop()); //鼠标移开后继续自动滚屏效果 swiper.$el[0].addEventListener('mouseleave', () => { listData.length > 1 && autoplay * 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> ) ) : ( <div style={{ height: '2px' }}></div> )} </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;