当前位置: 首页 > Web前端 > HTML

用React做一个滑动轮播展示组件

时间:2023-04-02 17:55:30 HTML

世间规则~无图无真相,先上传图片!这是一个展示列表的滑动轮播组件。单击左右按钮可左右滑动。每次可以滑动指定量,可以指定显示多少行内容。本人前端菜鸟,大佬们轻喷分享下面的代码,因为我是用React+Typescript做项目的。看不懂也没关系!换成普通的html和js类似。使用组件代码importReact,{Component,ComponentType}from'react'import{Icon}from'antd'import'./index.scss'接口IProps{cityList:Array,row:number,step:number}interfaceIStates{cityContainerWidth:number,cityWrapWidth:number,cityWrapTranslateX:number}classSliderextendsComponent{constructor(props:IProps){super(props)this.state={cityContainerWidth:0,cityWrapWidth:0,cityWrapTranslateX:0}}componentDidMount():void{const{cityList,row}=this.propsconstcityWrapWidth:number=cityList.length>12?Math.ceil(cityList.length/row)*220:1320常量cityWrapDom:HTMLElement|null=document.getElementById('city__wrap')作为HTMLElementconstcityContainerDom:HTMLElement|null=document.getElementById('city__container')作为HTMLElementconstcityContainerWidth:number=cityContainerDom.offsetWidthcityWrapDom&&(cityWrapDom.style.width=`${cityWrapWidth}px`)this.setState({cityContainerWidth,cityWrapWidth})}handleArrowClick(direction:string):void{const{step}=this.props常量{cityContainerWidth,cityWrapWidth,cityWrapTranslateX}=this.stateconstcityWrapDom:HTMLElement|null=document.getElementById('city__wrap')asHTMLElement/*步长*/consttranslateStep:number=220*stepconsttranslateDistance:number=translateStep*(direction==='left'?1:-1)letnewTranslateX:number=cityWrapTranslateX/*相对移动距离*/constrelativeTranslateX:number=cityContainerWidth-cityWrapTranslateXconstisLeftEnd:boolean=relativeTranslateX<=cityContainerWidthconstisLeftOverflow:boolean=relativeTranslateX-translateDistance<=cityContainerWidthconstisRightEnd:boolean=relativeTranslateX+th//这个10代表右边距10个像素,加上10个隐藏constisRightOverflow:boolean=relativeTranslateX-translateDistance>=cityWrapWidth/*点击左箭头*/if(translateDistance>0){/*是否到达左端*/if(isLeftEnd)returnif(isLeftOverflow){/*如果超出范围,则滑动距离刚好到达左侧末端*/newTranslateX=0}else{/*如果没有超出范围,滑动距离直接加到步长上*/newTranslateX+=translateDistance}}elseif(translateDistance<0){/*是否到达右侧终点*/if(isRightEnd)returnif(isRightOverflow){/*超出范围,则滑动刚好到右端的距离*/newTranslateX+=relativeTranslateX+10-cityWrapWidth}else{/*不超出范围,滑动距离直接加到步长上*/newTranslateX+=translateDistance}}consttransformString:string=`translateX(${newTranslateX}px)`cityWrapDom&&(cityWrapDom.style.transform=transformString)this.setState({cityWrapTranslateX:newTranslateX})}render(){const{cityList}=复制代码this.propsreturn(我是一个轮播图

this.handleArrowClick('left')}>
this.handleArrowClick('right')}>
{cityList.map(item=>({item}
))})}}将默认滑块导出为ComponentType样式文件(采用了sass来进行样式编写).city{&__container{position:relative;溢出:隐藏;宽度高:1200像素;填充顶部:10px;&::-webkit-scrollbar{width:15px;高度:15px;}&::-webkit-scrollbar-track{border-radius:20px;背景:#e7e7e7;}&::-webkit-scrollbar-thumb{背景:#66a6ff;背景图像:线性渐变(120deg,#89a4fe0%,#66a6ff100%);边界半径:20px;}}&__title{margin-top:30px;颜色:#333;字体大小:24px;字体粗细:粗体;}&__arrow{位置:绝对;显示:弹性;证明内容:居中;对齐项目:居中;顶部:50%;宽度:50px;高度:100px;背景:rgba(0,0,0,0.7);变换:翻译Y(-50%);过渡:所有.3s轻松;z-指数:2;不透明度:.5;游标:指针;&--右{右:0;}.icon{颜色:#fff;字体大小:30px;}&:hover{不透明度:1;}}&__wrap{transition:all.3sease-in-out;}&__item{浮动:左;宽度:210px;高度:90px;边距:010px10px0;颜色:#fff;字体大小:40px;字体粗细:粗体;行高:90px;文本对齐:居中;//背景:url(https://static.zhipin.com/zhipin-geek/v98/web/geek/images/city_101010100.png)不重复;//背景尺寸:覆盖;背景图像:线性渐变(135deg,#667eea0%,#764ba2100%);}}最后,这里出现的itemList是将要用于展示的数据列表这里我们可以使用一个函数来生成一个列表来展示。如果需要,可以用访问接口获取的list替换...getCityList():Promise>{returnnewPromise(async(resolve,reject)=>{constlength:number=15constcityList:Array=Array.from({length},(_:unknown,index:number):number=>index+1)resolve(cityList)})}我们生成了一个自然数数组[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]这里长度为15有评论,还是简单分享一下吧~步骤是的course:获取要展示的数据列表->将列表传递给滑动轮播组件->接受后根据列表的长度和展示的行数为容器设置动态宽度是亮点下一个!!!我在如何处理容器如何滑动方面下了很多功夫。让我们看一下监视箭头按钮点击的函数handleArrowClick(direction)。这个函数的意思是当点击左箭头时,方向为左。否则就是对的。this.handleArrowClick('left')}>this.handleArrowClick('right')}>分别是左右箭头,点击左箭头传递给函数输入一个字符串来表示方向定义step/*step*/consttranslateStep:number=220*stepconsttranslateDistance:number=translateStep*(direction==='left'?1:-1)这个很简单,就是根据父组件传入的step(每次点击滑动多少个元素),点击按钮时传入的方向。如果是左移,则移动距离为-stepsize。这里我们使用了transform:translateX的属性来滑动,正轴是向右的,所以如果要向右移动显示的内容,需要将移动的距离设置为负数,这样相对运动可以达到完美的预期效果。现在不明白没关系,我们继续往回看,得到移动距离,判断是否超出关键点!!!重点!!!重点!!!首先第一步是设置state,state定义了一个变量来表示已经滑动的距离,初始为0/*distancethathasbeenslid*/this.state={cityWrapTranslateX:0}然后我们得到滑动组件的外层容器和内层容器的宽度,不明白的可以自行百度轮播图的实现原理。简单解释就是外容器是可见的部分,内容器是会被隐藏的部分。然后,根据外层容器的大小,可以显示内层容器中的内容,也就是图中重叠的部分。想象一下~当内层容器左右移动的时候,我们看到的外层容器里面的东西也随之移动~OK,不懂的可以去百度找更详细的轮播图原理!我继续分析/*relativemovingdistance*/constrelativeTranslateX:number=cityContainerWidth-cityWrapTranslateX然后我们可以通过传入的外层容器cityContainerWidth的大小减去滑动距离cityWrapTranslateX得到相对移动距离,这是什么意思,继续说各种边界条件大家就明白了!constisLeftEnd:boolean=relativeTranslateX<=cityContainerWidthconstisLeftOverflow:boolean=relativeTranslateX-translateDistance<=cityContainerWidthconstisRightEnd:boolean=relativeTranslateX+10>=cityWrapWidth//这个10是代表右边距的10像素,加10隐藏constisRightOverflow=relativeTranslateX-translateDistance>=cityWrapWidth四个变量分别是:是否已经到了左边的尽头(不能再点击了!),点击按钮的左边是否会溢出(也就是滑动太远了!),是否已经到右侧结束,按钮右侧是否会溢出,我们主要分析后两者。后两者类似(因为我喜欢右边)。我们先假设外层容器宽度为1200,内层容器宽度为2000cityContainerWidth-cityWrapTranslateXconstisRightEnd:boolean=relativeTranslateX+10>=cityWrapWidth//这个10代表右边距10个像素,加上10隐藏,我们先忽略这个10,因为每个元素都有10px的边距,所以我们加上,我们可以忽略为什么会这样,假设我们的移动距离为0,那么相对距离就是外层容器的宽度,也就是1200,那么内层容器就是2000,比内层容器要小接下来,假设我们向右移动800px,那么cityWrapTranslateX就是-800(总之,记住内容向左为负数!)在这次我们的相对移动距离是1200-(-800)是2000,跟内胆是一样的,明白吗!这相当于把外层容器向右移动了800px,因为前面说了外层容器是控制我们的可见部分,所以外层容器在右边,也就是说内容也在右边,这是正确的!接下来看看这个constisRightEnd:boolean=relativeTranslateX+10>=cityWrapWidth就明白了。如果大于或等于,则表示已经到达终点。再次点击,不执行直接返回。isRightOverflow表示点击时不执行会超出容器范围。这是为了避免过度滑动和过多空白的问题。示例如下:由于过度滑动,右侧产生大量空白。那么我们来判断相对移动距离是否超过了容器内部的宽度,也就是超过了显示内容的宽度constrelativeTranslateX:number=cityContainerWidth-cityWrapTranslateXconstisRightOverflow:boolean=relativeTranslateX-translateDistance>=cityWrapWidth我们看一下现在幻灯片所在的图片,到最后只剩下300px,但是我们把每张幻灯片设置为600px,那么这个时候我们的相对移动distance是1200-(-500)是1700,那么relativeTranslateX-translateDistance是1700-(-600)是2300,大于2000,也就是说会溢出,溢出300px那么多,我们定义一个变量newTranslateX来表示新的滑动距离默认是最后一次滑动距离letnewTranslateX:number=cityWrapTranslateX如果快要溢出了,我们就设置为最后一次滑动距离加上相对滑动距离再减去内层容器的宽度。这个可能不太好理解,所以我们算一下newTranslateX=500(500已经滑动了)relativeTranslateX=1200cityWrapWidth=2000newTranslateX=500+1200-2000=-300这是否意味着向右移动了300个像素!,这样我们就走到了尽头!newTranslateX+=relativeTranslateX-cityWrapWidth最后我们可以根据各种情况设置最新的滑动距离。设置滑动距离后,可以改变样式/*点击左箭头*/if(translateDistance>0){/*到达左端*/if(isLeftEnd)returnif(isLeftOverflow){/*如果超出范围,那么滑动距离刚好到达左边的末端*/newTranslateX=0}else{/*如果没有超出范围,则滑动距离直接加到步长上*/newTranslateX+=translateDistance}}elseif(translateDistance<0){/*是否已经到达右侧末端*/if(isRightEnd)returnif(isRightOverflow){/*如果超出范围,则滑动刚好到达末端的距离右边的*/newTranslateX+=relativeTranslateX+10-cityWrapWidth}else{/*不超出范围,滑动距离直接加到步长上*/newTranslateX+=translateDistance}}consttransformString:string=`translateX(${newTranslateX}px)`cityWrapDom&&(cityWrapDom.style.transform=transformString)this.setState({cityWrapTranslateX:newTranslateX})我们会根据传入的行数来划分数据const{cityList,row}=this.propsconstcityWrapWidth:number=cityList.length>12?Math.ceil(cityList.length/row)*220:1320常量cityWrapDom:HTMLElement|null=document.getElementById('city__wrap')asHTMLElementcityWrapDom&&(cityWrapDom.style.width=`${cityWrapWidth}px`)这里简单判断有多少个元素,我们默认显示12个,两行,一个第6行,如果少于12个,则单独显示。设置为三行时:感觉整篇文章字数太多,很罗嗦,但也算是一个小总结,小菜鸡还是有些激动的写出来。你可以拿出一张纸和一支笔,在纸上画出示意图。可以快速摸清关系,再慢慢推开!