图片瀑布流+懒加载+无限下滑

图片瀑布流+懒加载+无限下滑

import React, { lazy, useEffect, useRef, useState } from 'react';
import styles from './index.less';
import InfiniteScroll from 'react-infinite-scroller';
import Macy from 'macy';
import LazyLoad from 'react-lazy-load';
import { useSetState } from 'react-use';
import { convert } from '@/utils';
import { useDispatch, useRequest, useSelector } from 'umi';

import { Spin } from 'antd';
import { post } from '@/utils/request';

interface EmptyProps {
  imgWidth?: number;
  innerWidth?: number;
  container?: string;
  Conmpont?: any;
  conHeight?: string;
  handlePic?: void;
  overPic?: any;
  overPicfooter?: any;
  margindis?: Object;
  columns?: number;
}

const PicMacy: React.FC<EmptyProps> = (props) => {
  const {
    imgWidth = 360,
    innerWidth,
    container = 'mainList',
    children,
    conHeight = 'calc(100vh - 68px)',
    overPic = () => {},
    overPicfooter = () => {},
    handlePic = (val: object) => {},
    margindis = { left: 16, top: 16 },
    columns = 6,
  } = props;
  const { userInfo } = useSelector((app) => app.user);

  const postqueryPicByLabelOrNot = (data) =>
    post('PortalPic/queryPicByLabelOrNot', data);

  const [scroller, setScroller] = useState({ isLastPage: false });
  const pageNum = useRef(1);
  const hasMore = useRef(true);

  //   const imgList = useRef([]);

  const [imgList, setImgList] = useState([]);
  const postqueryPicByLabelOrNotRequest = useRequest(postqueryPicByLabelOrNot, {
    manual: true,
    onSuccess: (data) => {
      if (data.list.length > 0) {
        pageNum.current = pageNum.current + 1;
        hasMore.current = true;
        setScroller(data);
        setImgList([...imgList, ...data?.list]);
        getMacy();
      }
    },
  });

  let masonry: any = null;
  const getMacy = () => {
    if (masonry) {
      masonry.reInit();
    } else {
      masonry = new Macy({
        container: `#${container}`, // 图像列表容器id
        trueOrder: false, // 不设置的话会顺序会乱
        waitForImages: false,
        useOwnImageLoader: false,
        debug: true,

        //设计间距

        //设置列数
        columns: columns,
        margin: { x: margindis.left, y: margindis.top },
      });
    }
  };

  useEffect(() => {
    lazyload();
  }, [imgList]);
  const lazyload = () => {
    // 创建 IntersectionObserver 实例
    const ob = new IntersectionObserver(
      (entries) => {
        for (let entry of entries) {
          if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src; // 将 data-src 的值赋给 src,实现图片加载
            ob.unobserve(img);
            getMacy();
          }
        }
      },
      {
        root: null, // 相对于整个视口进行判断
        rootMargin: '0px 0px 100px 0px', // 元素进入视口一段距离即触发
        threshold: [0, 0.1], // 元素完全进入视口时触发
      },
    );
    // 获取所有带有 data-src 属性的图片元素
    const imgs = document.querySelectorAll('img[data-src]');
    // 遍历图片元素,将每个元素绑定到 IntersectionObserver 上进行观察
    imgs.forEach((item) => {
      ob.observe(item);
    });
    // const additionalImgs = document.querySelectorAll(
    //   'img[data-src-additional]',
    // );
    // additionalImgs.forEach((item, index) => {
    //   if (index < 30) {
    //     item.src = item.dataset.srcAdditional;
    //   }
    // });
  };

  const getMore = () => {
    hasMore.current = false;
    if (userInfo.userId && !scroller.isLastPage) {
      postqueryPicByLabelOrNotRequest.run({
        currentPage: pageNum.current,
        userId: '1722523689024618496',
        pageSize: 50,
      });
    }

    // getMacy();
  };
  useEffect(() => {
    if (userInfo.userId) {
      getMore();
    }
  }, [userInfo]);

  return (
    <div className={styles.PicMacyLayout} style={{ height: conHeight }}>
      {children}

      <InfiniteScroll
        className="list-contents"
        initialLoad={true}
        pageStart={1} //首页为1,可根据自己的具体需求
        loadMore={async () => await getMore()}
        loader={
          !scroller.isLastPage && (
            <div style={{ textAlign: 'center' }}>
              <Spin spinning={true}></Spin>
            </div>
          )
        }
        useWindow={false} //****将滚动侦听器添加到窗口,或者添加组件的parentNode****
        hasMore={hasMore.current}
      >
        <div className={styles.recomandList} id={container} ref={scroll}>
          {imgList?.map((item, index) => {
            return (
              <div className={styles.item_box}>
                <div className={styles.recomandItem} key={index}>
                  <img
                    src={
                      'https://img0.baidu.com/it/u=1035818712,4106770352&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800'
                    }
                    className={styles.item_img}
                    data-src={item.pictureUrl}
                    style={{ width: `${convert(imgWidth)}` }}
                    onClick={() => handlePic(item)}
                  />

                  <div className={styles.overpic}>{overPic(item)}</div>
                  <div className={styles.overpic_footer}>
                    {overPicfooter(item)}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
        {scroller.isLastPage && (
          <div style={{ textAlign: 'center' }}>到底啦~</div>
        )}
      </InfiniteScroll>
    </div>
  );
};

export default PicMacy;

@import '../../assets/util.less';

.PicMacyLayout {
  overflow: auto;
  //   padding: 0 25px;
  .recomandItem {
    position: relative;

    .overpic {
      position: absolute;
      top: 0px;
      visibility: hidden;
    }
    .overpic_footer {
      position: absolute;
      bottom: 0px;
      visibility: hidden;
    }
  }
  .item_img {
    background: linear-gradient(0deg, #000000 0%, rgba(0, 0, 0, 0.43) 72%);
    border-radius: 14px;
  }
  .recomandItem:hover {
    .overpic {
      visibility: visible;
    }
    .overpic_footer {
      visibility: visible;
    }

    cursor: pointer;
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值