美文网首页
使用React实现无缝轮播

使用React实现无缝轮播

作者: 爱吃美食不爱长胖 | 来源:发表于2020-09-10 10:01 被阅读0次

    实现效果

    2020-09-10_095743.png

    js部分

    import React, { Component } from 'react'
    import { LeftOutlined, RightOutlined} from '@ant-design/icons'
    
    class Home extends Component {
        constructor(props) {
            super(props);
            this.state = {
                currentIndex: 0,
                carouselStyle: {},
                imageWidth: 500,
                imageHeight: 500,
                slideStyle: {},
                imgStyle: {
                    transform: 'scale(1.1)',
                    transition: 'all linear .3s'
                },
                defaultImgStyle: {
                    transform: 'scale(1)',
                    transition: 'all linear .3s'
                },
                speed: 0 // 不需要鼠标移入时可设置speed的值为2
            };
        }
        turn = () =>{ // 轮播
            if(this.timer) {
                clearInterval(this.timer)
            }
            this.timer = setInterval(()=>{
                this.go(1)
            },2 * 1000);
        }
        go = (step) => { // 去哪  传入要动几个
            console.log(this.state.currentIndex, 'currentIndex')
            let currentIndex = this.state.currentIndex + step;// 先加
            if(currentIndex >= this.itemsLength){ // 当等于最后一张时  越界回到0
                this.ul.style.transitionDuration ='0s';
                this.ul.style.left =0;
                setTimeout(()=>{// 等动画移除后并且回到了0点  再增加回动画时间(dom刷新一般是30s)
                    this.ul.style.transitionDuration = this.state.speed + 's';// 再增加回来这个动画
                    currentIndex = 0;// 下一次到第一张图
                    this.setState({currentIndex});
                },30)
                return;//因为设置了setTimeout所以要等待setTimeout后再设置最新状态
            }
            if(currentIndex < 0){// 当小于第一张时  回到最后一张
                this.ul.style.transitionDuration = '';// 清除ul上的动画
                this.ul.style.left = (this.itemsLength -1) * -1 * this.state.imageWidth + 'px';
                setTimeout(()=>{
                    this.ul.style.transitionDuration = this.state.speed + 's';
                    currentIndex = this.itemsLength -1; // 小于第一张时跳转到最后一张
                    this.setState({currentIndex});
                },30);
                return
            }
            this.ul.style.transitionDuration = this.state.speed + 's';
            const slideStyle = this.state.slideStyle
            this.setState({
                currentIndex,
                slideStyle: Object.assign(slideStyle, {
                    left: -1 * this.state.imageWidth * currentIndex + 'px',
                })
            })
        }
        stop = () => {
            clearInterval(this.timer)
            this.timer = null
        }
    
        handleMouseEnter = (e, index) => {
            e.preventDefault()
            this.stop()
            if(index) {
                this.setState({
                    imgStyle: {
                        transform: 'scale(1.1)',
                        transition: 'all linear .3s'
                    }
                })
                this.hoverIndex = index - 1
            }else {
                this.hoverIndex = null
            }
        }
        handleMouseLeave = (e, index) => {
            e.preventDefault()
            this.turn(true)
            this.ul.style.transitionDuration = this.state.speed + 's';
            if(index) {
                this.setState({
                    imgStyle: {
                        transform: 'scale(1)',
                        transition: 'all linear .3s'
                    }
                })
            }
            this.hoverIndex = null
        }
        linkToProduct = (id) => {
            console.log(id,this.$route, 'id')
            clearInterval(this.timer)
            this.timer = null
            window.location.hash = `#/products/${id}`
        }
        componentDidMount() {
            this.items = [
                {id: 1, src: require('../../assets/images/tu9.png')},
                {id: 2, src: require('../../assets/images/tu8.png')},
                {id: 3, src: require('../../assets/images/tu7.png')},
                {id: 4, src: require('../../assets/images/tu6.png')},
                {id: 5, src: require('../../assets/images/tu5.png')},
                {id: 6, src: require('../../assets/images/tu4.png')},
                {id: 7, src: require('../../assets/images/tu3.png')}
            ]
            this.itemsLength = this.items.length
    
            this.setState({
                carouselStyle: {
                    width: this.state.imageWidth + 'px',
                },
                slideStyle: {
                    // 宽度增加1倍
                    width: this.state.imageWidth * this.items.length * 2 + 'px',
                    left: 0
                }
            })
            this.hoverIndex = null
            this.turn()
        }
        componentWillUnmount() {
            clearInterval(this.timer)
            this.timer = null
        }
        render(){
            if(this.items && this.items.length) {
                return (
                    <div className={'home-box'}>
                        <div 
                            className={'carousel'} style={ Object.assign({overflow: 'hidden', heigth: this.imageHeight + 'px', width: '100%',marginTop: '20px'})}>
                            <ul className='slide' style={Object.assign({padding: 0}, this.state.slideStyle)} ref={(ul)=>{this.ul=ul;}}>
                                {this.items && this.items.map((item,index) => {
                                    return <li key={item.id} className={'img-box'} style={{width: this.state.imageWidth}}
                                        onMouseEnter={(e) => {this.handleMouseEnter(e, index + 1)}} 
                                        onMouseLeave={(e) => {this.handleMouseLeave(e, index + 1)}}
                                        onClick={() => {this.linkToProduct(item.id)}}
                                    >
                                        <img alt={index} src={item.src} style={this.hoverIndex === index ? this.state.imgStyle : this.state.defaultImgStyle}/>
                                    </li>
                                })}
                                {this.items && this.items.map((item,index) => {
                                    return <li key={'back_' + item.id} className={'img-box'} style={{width: this.state.imageWidth}}
                                        onMouseEnter={(e) => {this.handleMouseEnter(e, this.itemsLength + index + 1)}} 
                                        onMouseLeave={(e) => {this.handleMouseLeave(e, this.itemsLength + index + 1)}}
                                        onClick={() => {this.linkToProduct(item.id)}}
                                    >
                                        <img alt={index} src={item.src} style={this.hoverIndex === this.itemsLength + index ? this.state.imgStyle : this.state.defaultImgStyle}/>
                                    </li>
                                })}
                            </ul>
                            <div className={'left-control'} onMouseEnter={this.handleMouseEnter}  onMouseLeave={this.handleMouseLeave} onClick={() => {this.go(1)}}><LeftOutlined /></div>
                            <div className={'right-control'} onMouseEnter={this.handleMouseEnter}  onMouseLeave={this.handleMouseLeave} onClick={() => {this.go(-1)}}><RightOutlined /></div>
                        </div>
                    </div>
                )
            }else{
                return null
            }
        }
    }
    Home.defaultProps = {
      
    }
    export default Home
    

    css部分

    .home-box{
        background-image: url('../../images/timg.jpg');
        background-repeat: no-repeat;
        background-attachment: fixed;
        background-size: cover;
        /* background-position: center; */
        background-position: 0 4vh;
        min-height: 100vh;
    }
    .home-box .carousel{
        position: relative;
        height: 400px;
    }
    .home-box .carousel .slide{
        position: absolute;
        height: 400px;
        -webkit-transition-timing-function: linear;    /*之前是ease-out*/
        -moz-transition-timing-function: linear;
        -ms-transition-timing-function: linear;
        -o-transition-timing-function: linear;
        transition-timing-function: linear;
        margin: 0 auto;
    }
    .img-box{
        height: 400px;
        float: left;
    }
    .img-box img{
        width: 100%;
        cursor: pointer;
    }
    .left-control,
    .right-control{
        position: absolute;
        width: 50px;
        height: 100%;
        top: 0;
        font-size: 40px;
        background: transparent;
        align-items:center; 
        display: flex;
        cursor: pointer;
        color: rgb(0,98,148);
        opacity: 0;
    }
    .left-control{
        left: 0
    }
    .right-control{
        right: 0;
    }
    .carousel:hover .left-control,
    .carousel:hover .right-control{
        opacity: 1;
    }
    

    相关文章

      网友评论

          本文标题:使用React实现无缝轮播

          本文链接:https://www.haomeiwen.com/subject/bevuektx.html