react 实现手机端首页无缝轮播

    xiaoxiao2021-03-25  87

    首先要注明一下本人是首次写js相关博客,如有什么错误的地方,还请大家多多指正!谢谢!!!

    其中关于轮播部分有部分参考了一下这位前辈的代码,也是让我对无缝轮播有个清楚的概念,也很感谢这位前辈。 http://www.jianshu.com/p/1b1a06b579b2

    目前掌握的概念: 实现轮播可以采用transform中的translate,左移为transform: translate(-xx px) + transition:0.5s

    一共设置三层结构,最外层div为整个屏幕的宽度;ul为所有图片的宽度,可以设置为图片张数*100%;而里面每个li也是当前屏幕的宽度,可以设置为ul宽度/图片张数,这样使用translate时就可以实现translate(-屏幕宽度*当前图片位置)即可显示下一张图

    ``` html: <div class="slider"> <ul class="lunbo"> <li class="slider-item" style="width: 25%;"><img src="a"></li> <li class="slider-item" style="width: 25%;"><img src="b"></li> <li class="slider-item" style="width: 25%;"><img src="a"></li> <li class="slider-item" style="width: 25%;"><img src="b"></li> </ul> //下面部分为dot <div class="slider-dots-wrap"> <span class="slider-dot"></span> <span class="slider-dot"></span> </div> </div> 但是这样的话一旦图片张数轮播结束,后面就是空白,所以可以当图片轮播到最后一张时,将当前所在图片位置设置为0,即回到第一张 但是回到第一张时的动作会与轮播方向相反,因为如果你是左轮播,你的translate从负数转到0,会导致最后一张到第一张是右移 所以可以将需要轮播的图片重新一份加在后面,当然也可以复制第一张图片到最后,方法一样 本文图片为 图a图b图a图b,编号分别为012302相同,13相同,当到达3时跳到1继续轮播 ***react部分,其中轮播是一个slider组件 banner.tsx: //这是调用组件的那个文件,公司用到的是typescript // 从后台获取到图片数据data getBannerList(data){ data = data.concat(data);//复制所有图片加在后面 this.setState({BannerList: data, len: data.length}); } render(){ return ( <div className="slider-box"> <Slider items={this.state.BannerList} len={this.state.len} speed={0.5} delay={3} autoplay={true}/> </div> ); } 当图片到达最后一张时,将this.now = 1,transitionnonetransform:translate(-320px),这个过程是瞬间的,肉眼看不出来,然后可以正常左滑 Slider 组件 touchstart = this.touchStart.bind(this); touchmove = this.touchMove.bind(this); touchend = this.touchEnd.bind(this); //设置transform cssTransform(ele, attr, val){ if(!ele.transform){ ele.transform = {}; }; //当传入值时对属性进行设置。 if(arguments.length > 2){ ele.transform[attr] = val; var sval = ''; for(var s in ele.transform){ if(s === 'translateX'){ sval += s + '(' + ele.transform[s] + 'px)'; } //如果实在不理解,可以console.log(sval)可以看到到最后一张时会有一个先跳到第二张再快速到第三张的过程 ele.style.WebkitTransform = ele.style.transform = sval; } } else{ val = ele.transform[attr]; if(typeof val === 'undefined'){ if(attr === 'translateX'){ val = 0; } }; return val; } } //自动轮播 auto(){ clearInterval(this.timer); this.timer = setInterval(() => { //当到达最后一张时 if(this.now === this.props.len - 1){ this.now = this.props.len / 2 - 1; //这两句代码很重要,是实现的关键,none是为了不出现平移而是直接跳变 this.LunBoEle.style.transition = 'none'; this.cssTransform(this.LunBoEle, 'translateX', - this.now * this.sliderWidth); } //定时是为了tab函数中执行的csstransform函数与上面到达最后一张时的csstransform有先后,不然仍会导致右移; setTimeout(() => { this.now++; this.tab(); }, 30); }, this.props.delay * 1000); } tab(){ this.LunBoEle.style.transition = '.5s'; this.cssTransform(this.LunBoEle, 'translateX', -this.now * this.sliderWidth); let SelectIndex = this.now % (this.props.len / 2); $('.slider-dots-wrap span').eq(SelectIndex).addClass('slider-dot-selected').siblings().removeClass('slider-dot-selected'); } componentDidMount() { this.LunBoEle = document.querySelector('ul.lunbo'); this.SliderEle = document.querySelector('.slider'); this.sliderWidth = $('.slider').width(); this.cssTransform(this.LunBoEle, 'translateX', 0); this.auto.bind(this)(); this.SliderEle.addEventListener('touchstart', this.touchstart, false); this.SliderEle.addEventListener('touchmove', this.touchmove, false); this.SliderEle.addEventListener('touchend', this.touchend, false); } //触发 touchStart(e: TouchEvent){ e.stopPropagation(); if(!this.stopped){ clearInterval(this.timer); this.LunBoEle.style.transition = 'none'; let moveX = this.cssTransform.bind(this)(this.LunBoEle, 'translateX'); this.now = Math.round(-moveX / this.sliderWidth); if(this.now === 0){ this.now = this.props.len / 2; }else if(this.now === this.props.len - 1){ this.now = this.props.len / 2 - 1; } this.cssTransform(this.LunBoEle, 'translateX', -this.now * this.sliderWidth); this.startPoint = e.changedTouches[0].pageX; this.startEle = this.cssTransform.bind(this)(this.LunBoEle, 'translateX'); } }; //移动 touchMove(e: TouchEvent){ e.preventDefault(); e.stopPropagation(); if(!this.stopped){ let endPoint = e.changedTouches[0].pageX; let disX = endPoint - this.startPoint; this.cssTransform.bind(this)(this.LunBoEle, 'translateX', disX + this.startEle); } } //平移结束 touchEnd(e: TouchEvent){ e.stopPropagation(); if(!this.stopped){ let moveX = this.cssTransform.bind(this)(this.LunBoEle, 'translateX'); //这边我是对移动做了判断 if(Math.abs(moveX) > Math.abs(this.now * this.sliderWidth)){ this.now = Math.ceil(-moveX / this.sliderWidth); }else{ this.now = Math.floor(-moveX / this.sliderWidth); } this.tab.bind(this)(); this.auto.bind(this)(); } } componentWillUnmount(){ //注意这边的清楚很重要,因为用户在使用时如果后台修改,用户刷新,会导致下面的dot出现问题 clearInterval(this.timer); //卸载的同时需要将所有事件清除掉 this.SliderEle.removeEventListener('touchstart', this.touchstart, false); this.SliderEle.removeEventListener('touchmove', this.touchmove, false); this.SliderEle.removeEventListener('touchend', this.touchend, false); } //防止如果只有一张轮播图时进行轮播 componentDidUpdate(){ if((this.props.len / 2) === 1){ clearInterval(this.timer); this.stopped = true; } else{ this.stopped = false; } } render() { let itemNodes = this.props.items.map((item, idx) => { return <SliderItem item={item} count={this.props.len} key={'item' + idx} />; }); let dotNodes = []; let count = this.props.len / 2; for(let i = 0; i < count; i++){ //为第一个dot点加上selected dotNodes[i] = ( <span key={'dot' + i} className={'slider-dot' + (i === 0 ? ' slider-dot-selected' : '')}> </span> ); } return ( <div className="slider"> <ul className="lunbo" style={{width: (this.props.len) * 100 + '%'}}> {itemNodes} </ul> <div className="slider-dots-wrap"> {dotNodes} </div> </div> ); }; sliderItem.tsx render(){ //设置li 的宽度,100指的是ul宽度的100% let width = 100 / (this.props.count) + '%'; let img =<img src={this.props.item.imageurl}/> return ( <li className="slider-item" style={{width: width}}> {img} </li> ); }

    初次分享结束,希望我的代码对你有用哈~ 我是个妹子哈,所以要喷的话请轻喷~~哈哈~

    转载请注明原文地址: https://ju.6miu.com/read-21733.html

    最新回复(0)