react中实现系统公告-左右循环滚动(首尾衔接)

组件名称:系统公告
描述:悬浮的公告栏,作用于一条消息,长度不定,公告栏宽度自适应屏幕
代码场景:react,hooks,tsx,less
功能介绍:
1.内容根据宽度自适应,无法显示完整将自动滚动,如果满足显示则居中不动
2.左右滚动,首尾衔接模式滚动,(尾部只有可视化区域一半,首部将衔接从右边显示)
注:初品,未做过多的封装功能与扩展功能,个人喜好一般自己有能力写出来的组件尽量不用插件,长远角度对维护项目/自己都有好处,有好的优化或者不明白的在下方评论留言
index.tsx
/** @Author: 刘强* @Date: 2022-02-08 10:18:06* @LastEditTime: 2022-02-08 15:11:58* @LastEditors: 刘强* @Description: 公告* 这是注释!*/import React, { useState, useEffect } from 'react';
import './index.less';let tagTimer: any = null; //元素初始化计时器
let tagConutStatic: number = 0; //初始化执行统计
let scrollTimer: any = null; //滚动计时器
let moveNumberStatic: number = 0;
let maxMoveStatic: number = 0;
let maxViewStatic: number = 0;
let ceshi = '本平台目前提供的通道带积分本平台目前提供的通道带积分,';const Notice = () => {const [visible, setVisible] = useState<boolean>(true); //公告显示const [isScroll, setIsScroll] = useState<boolean>(false); //是否滚动-控制预留const [moveNumber, setMoveNumber] = useState<number>(0); // 当前滚动距离const [maxMove, setMaxMove] = useState<number>(0); // 最大滚动距离const [maxView, setMaxView] = useState<number>(0); // 最大可视距离const [context, setContext] = useState<String>(''); //公告内容const [list, setList] = useState<Array<String>>([]); //公告内容const [tagConut, setTagConut] = useState<number>(0); //初始化执行统计// api 获取公告内容-后期接入服务端的接口就行了function getNoticeApi() {setContext(ceshi);setList([ceshi]);tagTimer = setInterval(() => {tagConutStatic++;setTagConut(tagConutStatic);}, 300);}// 计算是否需要滚动function checkScrollFn() {try {let dom = document.getElementsByClassName('notice-scroll')[0];if (!dom || dom.clientWidth === 0) return;let maxWidth =document.getElementsByClassName('notice-context')[0].clientWidth;let newWidth = dom.clientWidth;setIsScroll(newWidth > maxWidth);setMaxMove(newWidth);setMaxView(maxWidth);clearInterval(scrollTimer);if (newWidth > maxWidth && list.length < 2) {noticeScrollFn();setList([context, context]);} else {clearInterval(scrollTimer);scrollTimer = null;}clearInterval(tagTimer);tagTimer = null;} catch (error) {console.log(error);}}// 滚动公告function noticeScrollFn() {scrollTimer = setInterval(() => {if (-moveNumberStatic > maxMoveStatic) {setMoveNumber(maxViewStatic / 2 - 3);// dom.push()} else {setMoveNumber(moveNumberStatic - 3);}}, 150);}// 渲染公告列表function renderList() {return list.map((item, index) => {return (<spankey={index}style={{transform: `translateX(${moveNumber + (maxView / 2) * index}px)`,}}className="notice-scroll">{item}</span>);});}//初始化公告useEffect(() => {getNoticeApi();}, []);// 公告接收开始计算useEffect(() => {checkScrollFn();}, [tagConut]);useEffect(() => {moveNumberStatic = moveNumber;}, [moveNumber]);useEffect(() => {maxMoveStatic = maxMove;}, [maxMove]);useEffect(() => {maxViewStatic = maxView;}, [maxView]);return (<div id="notice" className={`${visible ? '' : 'notice-hidden'}`}><divclassName={`notice-context ${isScroll ? '' : 'notice-noscroll'}`}>{renderList()}</div><spanonClick={() => {setVisible(false);}}className="iconfont iconclose"></span></div>);
};export default Notice;
index.less
#notice {position: fixed;top: 70px;width: 100vw;height: 40px;box-sizing: border-box;padding: 0 20px 0 50px;display: flex;align-items: center;justify-content: space-between;background-color: @disabled;z-index: 1000;.notice {&-context {color: #000;font-size: 14px;width: calc(100% - 30px);text-align: center;overflow: hidden;display: flex;}&-scroll {display: inline-block;white-space: nowrap;transition: all 0.3;}&-noscroll {justify-content: center;}}.iconclose {cursor: pointer;font-size: 14px;color: @white-close; //关闭颜色&:hover {color: @white-hover; //关闭颜色}}
}
.notice-hidden {display: none !important;
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
