时间轴组件(TimeLine)自定义封装

1,057 阅读2分钟

效果图:

image.png

index.tsx
 class TimeLine extends React.Component<any,any> {
     constructor(props) {
        super(props)
        this.state = {
            left:0,
            curStepIndex:2
        }
    }
    
    //时间轴事件
    goleft = () => {
        if(this.state.curStepIndex > 2){
        this.setState({
            left:this.state.left + (document.body.clientWidth / this.props.number),
            curStepIndex:this.state.curStepIndex - 1
            })
        }
        }
        
    goRight = () => {
        if(this.state.curStepIndex < this.props.breakOption.length){
            this.setState({
                left:this.state.left + (-document.body.clientWidth / this.props.number),
                curStepIndex:this.state.curStepIndex + 1
                })
        }
    }
    
    render() {
        let { style = {}, breakOption = {}, topTextStyle = {}, bottomTextStyle = {}, number = 5} = this.props

        return (
            <div>
                <div className={styles.timeLineContainer} style={style}>
                <div className={styles.timeLine} style={{borderTop:"3px solid #3ED2E2",left:this.state.left}}>
                    {
                    breakOption.map((item, index) => {
                        return <div key={index} className={styles.steps} style={{width:`calc(100vw / ${number})`}}>
                                <div className={`${styles.point} ${index <= this.state.curStepIndex ? styles.activePoint : ''}`}></div>

                                {
                                    item.topText? 
                                    <div className={[styles.topBox,styles.box].join(' ')}>
                                        {item.topIcon? <img className={[styles.topIcon,styles.icon].join(' ')} src={item.topIcon} alt="" />:''}
                                    <div>
                                            <p className={styles.title} style={item.topTextStyle?.title?item.topTextStyle?.title:{}}>{item.topText ? item.topText : ''}</p>
                                            <p className={styles.description} style={item.topTextStyle?.description?item.topTextStyle?.description:{}}>{item.topDescription ? item.topDescription : ''}</p>
                                    </div>
                                    </div>:''
                                }
                                {
                                    item.bottomText?
                                    <div className={[styles.bottomBox,styles.box].join(' ')}>
                                        {item.bottomIcon? <img className={[styles.bottomIcon,styles.icon].join(' ')} src={item.bottomIcon} alt="" />:''}
                                        <div>
                                            <p className={styles.title} style={item.bottomTextStyle?.title?item.bottomTextStyle?.title:{}}>{item.bottomText ? item.bottomText : ''}</p>
                                            <p className={styles.description} style={item.bottomTextStyle?.description?item.bottomTextStyle?.description:{}}>{item.bottomDescription ? item.bottomDescription : ''}</p>
                                        </div>
                                    </div>:''
                                }
                            </div>
                    })
                }
            </div>
          </div>

        <div className={styles.timeLinebtnBox}>
            <CaretLeftOutlined className={styles.rightBtn} onClick={this.goleft}/>
            <CaretRightOutlined className={styles.leftBtn} onClick={this.goRight}/>
        </div>
    </div>
    )}}
   export default TimeLine
styles.module.scss
.timeLineContainer {
        padding:250px 0;
        position: relative;
        user-select: none;
  
        .timeLine {
              padding: 0 100vw 0 50px;
              border-radius: 2px;
              transition: all .3s;
              display:flex;
              position:absolute;
        }
        .steps{
              position:relative;
        }
        .point {
              position: absolute;
              left:0;
              top: -8px;
              width: 8px;
              height: 8px;
              border-radius: 50%;
              background-color: #06187D;
              box-shadow: 0 0 0 5px #D8D8D8;
        }
  
        .activePoint {
              background-color: #67D9FF;
              box-shadow: 0 0 0 5px #2093FF;
        }
        .box{
              position: absolute;
              left:4px;
              height:150px;
              padding-left:30px;
              border-left:2px dashed #3ED2E2;
              display:flex;
          p{
                margin-bottom: 0;
           }
        }
            .topBox {
                  bottom: 14px;
            }
            .bottomBox {
                  top:4px;
                  align-items: flex-end;
            }
            .title{
                 font-size: 20px;
                 font-weight: bold;
                 line-height: 27px;
                 color:black;
                 margin-bottom:10px !important;
            }
            .description{
                 font-size:15px;
                 color:rgba(0,0,0,0.9)
            }
           .icon{
                width:40px;
                height:40px;
                position:absolute;
            }
           .topIcon{
                top:-40px;
                left:-20px;
           }
           .bottomIcon{
                top:150px;
                left:-20px;
           }
        }
    .timeLinebtnBox{
        text-align: center;
           .rightBtn,.leftBtn{
            font-size:50px;
            color:#2093FF;
        }
    }
页面调用
const  breakOption=[
    {
        topText: '2022年1月',
        topDescription:<Translate id="CompanyProfile.timeLine.description1">The only domestic framework LakeSoul open source</Translate>,
        //国产唯一湖仓框架 LakeSoul 开源
        topIcon:require('@site/static/companyProfile/icon1.png').default,
        active: true,
    }, 
    {  
        bottomText: '2022年3月',
        bottomDescription:<Translate id="CompanyProfile.timeLine.description2">One-stop machine learning platform MetaSpore open source</Translate>, 
        // 一站式机器学习平台MetaSpore开源
        bottomIcon:require('@site/static/companyProfile/icon2.png').default,
        active: true 
    }, 
    {
        topText: '2022年5月',
        topDescription:<Translate id="CompanyProfile.timeLine.description3">AI development and production platform AlphalDE opens private beta</Translate>, 
        //AI开发生产平台AlphaIDE开放内测
        topIcon:require('@site/static/companyProfile/icon3.png').default,
        active: false,
    }, 
    { 
        bottomText: '2022年7月', 
        bottomDescription:<Translate id="CompanyProfile.timeLine.description4">The only domestic open-source LakeSoul 2.0 released</Translate>, 
        //国产唯一开源湖仓 LakeSoul 2.0 发布
        bottomIcon:require('@site/static/companyProfile/icon4.png').default,
        active: false 
    },
    { 
        topText: '2022年8月', 
        topDescription:<Translate id="CompanyProfile.timeLine.description5">Jointly hold the Data Lake Flow Batch Integrated Performance Optimization Challenge with CCF.</Translate>, 
        //联合 CCF 共同举办数据湖流批一体性能优化挑战赛
        topIcon:require('@site/static/companyProfile/icon5.png').default,
        active: false 
    },
    {  
        bottomText: '2022年9月', 
        bottomDescription:<Translate id="CompanyProfile.timeLine.description6">In cooperation with the Beijing University of Posts and Telecommunications laboratory, Prof.Wang Pengfei joined the MetaSpore open-source community.</Translate>, 
        //与北京邮电大学实验室达成合作,王鹏飞老师团队加入 MetaSpore 开源社区
        bottomIcon:require('@site/static/companyProfile/icon6.png').default,
        active: false 
    },
    { 
        topText: '2022年10月',  
        topDescription:<Translate id="CompanyProfile.timeLine.description7">It is recommended to log in to Shopify, the largest independent site construction platform.</Translate>, 
        // 推荐 SaaS 产品登录最大独立站建站平台 Shopify
        topIcon:require('@site/static/companyProfile/icon7.png').default,
        active: false 
    },
    {  
        bottomText: '2022年11月', 
        bottomDescription:<Translate id="CompanyProfile.timeLine.description8">Won the Zhongguancun high-tech enterprise certification</Translate>, 
        // 荣获中关村高新技术企业认证
        bottomIcon:require('@site/static/companyProfile/icon8.png').default,
        active: false 
    },
    { 
        topText: '2022年12月',  
        topDescription:<Translate id="CompanyProfile.timeLine.description9">Intel "Innovation Master Cup" global Al Geek Challenge preliminary, rematch double top: Personalized recommendation SaaS service is coming to the major public cloud</Translate>, 
        // 英特尔“创新大师杯”全球AI极客挑战赛初赛、复赛双榜第一;个性化推荐 SaaS 服务即将登陆各大公有云
        topIcon:require('@site/static/companyProfile/icon9.png').default,
        active: false 
    },
    {  
        bottomText: '2023年1月', 
        bottomDescription:<Translate id="CompanyProfile.timeLine.description10">It was awarded the Top 10 most potential start-up of the Heart of the Machine.</Translate>, 
        // 荣获机器之心最具潜力创业企业Top10
        bottomIcon:require('@site/static/companyProfile/icon10.png').default,
        active: false 
    },
]
  const [number,setNumber] = useState(5)
    useEffect(() => {
    if(document.body.clientWidth<768){
        setNumber(()=>{
            return 2
        })
    }
    },[])
    ...
    <TimeLine breakOption={breakOption}  number={number} className={styles.timeLine}/>
    ...

记录我的第一篇~

啊哈~