美文网首页
使用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