基于react做的消息轮播

39 阅读2分钟

又来组件积累了,为了少加班,今天写了个消息单条轮播,先记下笔记,以后方便复制。经常用于首页消息通知。

import { useEffect, useState, useRef,useLayoutEffect } from 'react';
import styles from './comp.module.less';
const NoticeCarousel = props => {
  const { notifications = [] } = props;
  console.log('notifications',notifications)
  let timer;
  let activeIndex = 0;
  let shouldReset = false;
  let moving = false;
  const interval = 4000;
  const animationDuration = 500;
  const swiperHeight = 30;
  const noticeBarList = useRef();
  const [firstItem, setFirstItem] = useState(null);
  const listRef = useRef();
  const [list, setList] = useState([]);

  function transitionEnd() {
    moving = false;
    const currentIndex = activeIndex;
    if (shouldReset) {
      shouldReset = false;
      swiperDoTransition(currentIndex, 0);
      if(!firstItem) return;
      firstItem.style.transform = '';
    }
  }

  function next() {
    const nextIndex = activeIndex + 1;
    const isLastItem = nextIndex >= list.length;
    moving = true;
    swiperDoTransition(nextIndex, animationDuration);
    if (isLastItem) {
      activeIndex = 0;
      shouldReset = true;
      if(!firstItem) return;
      firstItem.style.transform = `translate3d(0, calc(${nextIndex} * ${swiperHeight}px), 0)`;
    } else {
      activeIndex += 1;
    }
  }

  function autoPlay() {
    console.log('list', list);
    console.log('list', list.length);

    if (list.length <= 1) return;
    timer && clearInterval(timer);
    timer = setInterval(() => {
      !moving && next();
    }, interval + animationDuration);
  }

  function swiperDoTransition(index, duration) {
    const transformY = `translate3d(0, calc(-${index} * ${swiperHeight}px), 0)`;
    if(!noticeBarList.current) return;
    noticeBarList.current.style.transitionDuration = `${duration}ms`;
    noticeBarList.current.style.transform = transformY;
  }
  useLayoutEffect(() => {
    setFirstItem(noticeBarList.current.firstElementChild);
    setList(noticeBarList.current.children);
  }, []);
  useLayoutEffect(() => {
    timer = null;
    noticeBarList.current.addEventListener('transitionend', transitionEnd);
    setTimeout(() => {
      autoPlay();
    }, 2000);
    return () => {
      timer && clearInterval(timer);
    };
  }, [list]);

  return (
    <div className={styles['page-container']}>
      <div className={styles['noticebar']}>
        <div className={styles['noticebar-list-container']}>
          <div className={styles['noticebar-list']} ref={noticeBarList}>
            {notifications?.map(i => (
              <div className={styles['noticebar-item']} key={i.messageId} ref={listRef}>
                <div className={styles['custom-notice-item']}>
                  <p className={styles.notice} dangerouslySetInnerHTML={{ __html: i.content }} />
                </div>
              </div>
            ))}
          </div>
        </div>
        {/* <div className={styles['noticebar-close-icon']}>
          <img
            src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAAXNSR0IArs4c6QAAAfZJREFUaEPt2u1NwzAQBuBLukDZABaoEN2hYgvKCEwAI7ABsAUfI6BIFAaADegCxMgSkUKaj7N97zlK3L91XD9+nSY+OaOZfbKZeSmBp554SjglPLEZSEt6YoEecFLCXQmv1psLIrolon1O+c1b8fgQczX4joed8Gq9+SSi4wqZU76Nhf7D3tcmfP9ePB9xAnABfxPRst5pDHQLljLKvnbF04ko+PTsfFtm5V2zU010G9aOx+Tm8uP1pZ54p52dsO0hJloCaw1O4FhoKawXWBstifUGa6GlsUFgNBqBDQaj0CisCFgajcSKgaXQaKwoOBStgRUH+6K1sBCwK1oTCwNz0dpYKHgIXVJpmxy88LtsBDi7o2Yb53dp1x/p2nC09YPGwhOuUBy0BlYN3Le87XdaWFVw1x+UHYRmEQF+D1tQH7Za9lpoOJiD1URDwX3P2cXPgmLUyGBgzktFjBoZBMzBDj2yUPe0ONgFGwMtCvbBaqPFwCFYTbQIWAKrhQ4GS2I10EFgBBaN9gYjsUi0F1gDi0I7gzWxCLQTOAZWGs0Gx8RKol3A/854aFcqBtD4Mx6aZZlmwa+5y4Kd8TCZuSYyyzI3V9wzFa5VTm57i/YZD3tJcwcy9nYJPPaEQseXEg6dwbFfnxIee0Kh40sJh87g2K+fXcK/GTb9TA793a8AAAAASUVORK5CYII="
            alt=""
          />
        </div> */}
      </div>
    </div>
  );
};
export default NoticeCarousel;



样式

/*** 通知栏轮播部分 ***/
.page-container {
  width: 100%;
  overflow: hidden;
  .noticebar {
    width: 100%;
    --height: 30px;
    box-sizing: border-box;
    color: #2e3346;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    .noticebar-list-container {
      width: 100%;
      height: var(--height);
      overflow: hidden;
      flex-shrink: 0;
    }
  }
  .noticebar-close-icon {
    width: 15px;
    height: 15px;
  }
  img {
    display: block;
    width: 100%;
    height: 100%;
  }
  .noticebar-item {
    height: var(--height);
    align-items: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    .notice {
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
    }
  }
  .custom-notice-item {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex-shrink: 0;
    line-height: 30px;
  }
}