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