轮播效果在网页中用的很多斯威珀是其中最有代表性的作品,它支持水平和竖直滑动,还有反弹效果,兼容移动端和个人计算机端。当然代码量也是相当大的,单是射流研究…就有5300行(3.4.0的未缩版本),若不考虑代码利用率和加载速度直接就用了,在移动端比较慎重,比如京东(m.jd.com)的轮播就没有用它,而是自己实现了类似的功能,代码量很少的样子(格式化之后看起来二三百行左右的样子)。那么这个功能如果自己来实现,要怎么做呢?
准备工作
1.准备几张图片(我这里放了四张)
2.搭建目录结构(html css图像js)
3.编写代码,实现初始状态的显示效果
!DOCTYPE htmlhtmlhead元字符集='utf-8 '元名称=“视口”内容='宽度=设备宽度,初始比例=1,最小比例=1,最大比例=1,用户可缩放=无/title轮播/title link rel='样式表type=' text/CSS ' href=' Slider。CSS ' rel='外部无跟随'脚本src=' http : Slider。js '/script/head dy div id=' Slider ' class=' Slider-wrapper ' ul class=' Slider-items ' Li class=' Slider-items ' img src=' http : images/pic 21。gif ' alt=' 1 '/Li Li class=' Slider-item ' img src=' http p3p/脚本/正文/html写几行样式,先让页面有一种滚动前的初始画面。
车身{ padd : 0;最小宽度: 300像素;最大宽度: 640像素;margin: 0 auto} ul {列表式:无;} ul,李{保证金: 0;padd : 0;} .滑动包装器{相对位置:宽度: 100%;高度: 220 px飞越:隐藏;-网络工具包-用户-选择:无;-ms-用户-选择:无;用户选择:无;} .滑块项目{相对位置:高度: 100%;} .滑块项目{左侧浮动:文本对齐:中心;光标:指针;} .滑块项目img { width : 100%;指针事件:无;} .滑块分页{位置:绝对值;bottom : 10pxleft : 0;宽度: 100%;文本对齐:中心;-网络套件-过渡-持续时间:3s;蚊子过渡-持续时间3s-o-过渡-持续时间3s过渡-持续时间3s}。滑块-项目符号{ width : 8pxheart : 8pxmargin 3360 0 5pxdisplay :内联块;边界半径: 100%;背景-颜色:黑色;opa city 3360 . 2 cursor :指针;} .滑块-项目符号-活动{ opa city 3360 1;背景色: # 007 aff} .滑动按钮{ position : absolute top : 50%;宽度: 50px高度: 50px文本对齐:中心;线高: 50px边距-top :-25px;z指数: 10;font-size : 4 rem颜色:灰色;-网络工具包-用户-选择:无;用户选择:无;} .下一个{ right: 0px}。prev { left: 0px}
做好这个静态页,可以帮助我们在开发过程中预览效果,方便查找问题,欣赏制作过程带来的乐趣。
在线预览
搭建程序骨架
接下来就是写射流研究…了,先搭一个程序的架子,我这里仿一下日本季刊日本季刊的无新的式设计(其实是自己在内部自动实现新的的过程)
;(function(global,factory){ ' use strict ';if(type of module==' object ' type of module . exports==' object '){ module . exports=global . document?工厂(全局,真):函数(w ) { if(!w.document ) {抛出新错误(' Slider需要一个带文档的窗口');}返厂(w);};} else { factory(全局);} //如果尚未定义窗口,则传递此信息})(窗口类型!=='未定义'?window :这个,函数(window,noGlobal ){ '使用strict ';函数Slider(选择器,选项){返回新的Slider.init(选择器,选项);} Slider.init=function(选择器,参数){ next:function(){},br prev:function(){},br move : function(){ } } br slider . init . prototype=slider . prototype={ brbr };返回滑块});架子搭好之后,停下来喝一杯,想想我们的插件最终会实现什么功能。
1.单击左右箭头控制滚动
3.您可以向左和向右拖动和滑动
4.反弹效应
5.自动旋转效果
6.页码指示
如何实现这些功能?
先画几个草图,在纸上模拟这个过程,然后用代码让计算机执行。下图中的蓝色方框代表显示器的宽度,红色方框代表图片所在容器的实际宽度。只要我移动红框,它就会出现在屏幕上,起到旋转滚动的效果。原理看起来简单吗?本着先易后难、循序渐进的操作方针,不考虑先循环碾压。假设画面1显示在屏幕上。此时,只需将红框向左移动一屏宽,那么它就会显示2,然后将一屏移动到显示3。向右滚动正好相反。
移动可以通过css3的transform:translate3d,或者通过更改js的左/顶部来完成。translate3d的核心代码如下:
函数translate3d(元素,x,y) { x=x===undefined?0 : x;y=y===未定义?0 : x;element . style['-web kit-transform ']=' translate 3d(-' x ' px,' y 'px,0px)';element . style[' transform ']=' translate 3d(-' x ' px,' y 'px,0px)';}功能转换(元素,时间){ element . style['-web kit-transition-duration ']=时间' ms ';element . style[' transition-duration ']=时间' ms ';}x控制左右移动,y控制垂直移动(本例中不考虑),z固定(0px)。当x移动的距离为正时,它会向左滚动,当它为负时,它会向右滚动
fn . next=function(){ var active index=this . active index;translate3d(this.wrap,active index * this . slide width);过渡(this.wrap,this . params . speed);} fn . prev=function(){ var active index=-this . active index;translate3d(this.wrap,active index * this . slide width);过渡(this.wrap,this . params . speed);}因为图片数量有限,不能一直滚动。如果结束了,你需要做一些处理。因此,需要判断activeIndex(当前显示的图片索引)的值。如果您到达最右侧,您将不再允许滚动。
var active index=this . last index-;brif(active index this . last index){ return;}同样的道理,当你到了最左边,你就不能继续向左滚动了(听起来像是很正确的废话)
var active index=-this . active index;if(active index this . first index){ return;}现在要考虑自动滚动的情况。如果是自动转盘,不能直接退回;或者到达最右边时,将activeIndex赋给firstIndex,到达最左边时,将activeIndex赋给lastIndex这样做的实际效果看起来像是荡秋千,这显然不是我们想要的。或者跳到前面重新开始,实际效果一点都不连续。最后,我决定看看swiper是如何实现的。Swiper的做法是把第一份放在后面,最后一份放在前面。如下图所示:
第一张和第四张都被复制了。相应的代码如下:
fn . CreateLoopItems=function(){ var LastItem=this . slides[this . LastIndex];var first item=this . slides[this . first index];var prevItem=last item . clonenode(true);var next item=first item . clonenode(true);var slider count=this . slider count 2;var slide width=this . slide width;this . slide stack . push(this . first index);this . slide stack . unshift(this . last index);this . wrap . insert before(previitem,first item);this . wrap . appendchild(next item);this . wrap . style . width=slide width * slider count ' px ';translate3d(this.wrap,slide width);this . active index=1;this.sliderCount=sliderCountthis . last index=2;}我不得不承认这种做法很高明。无论我们转向哪个方向,都不会有空白期。当你翻到最后一页(第四页)时,你可以翻开另一页,也就是第一页的副本,虽然它不是真正的第一页,但看起来像是平稳过渡到第一页。但是,这是暂时的,我们需要在过渡后立即回到真正的1位置。因为我们其实最后只加了一个,如果翻过这一页,不进一步处理就结束了。这时,才是问题的关键。当我们向右拐的时候,从第四个副本到第一个副本,我们需要把红框的位置悄悄移到1的真实体。同时,activeIndex也被设置为图1的索引。那么问题又来了,怎样才能让人在不知情的情况下潜入黑暗?其实很简单,只需要将移动动画的时间改为0即可。关键代码如下:
过渡(this.wrap,0);但是,当此步骤从4停止到1时,应立即执行。如果做得早,会觉得直接从4跳到1,没有动画效果。如果做得晚,会有一个空白,并且会因为索引溢出而报告错误。因此需要一种修复方法:
fn . fixedprevloop=function(){ var那=thissetTimeout(function(){ that . fixed loop(that . last index-1)},that . params . speed);}或:
这个。集装箱。addeventlistener(' transition end ',function(){ br//执行修复判断前监控动画速度br},false);经过这一步,似乎有了连续滚动的效果。在此基础上很容易实现自动轮播,只是偶尔用一个定时器来执行自己。代码如下:
fn.autoPlay=function(){ var那=thisif(!this . params . autoplay){ return;} this . timeid=setTimeout(function(){ that . next();//that . prev();that . autoplay();},this . params . delay);}我注释掉了prev(),默认是右边的自动轮播。如果您想将其更改为广播到左轮,只需在此添加一个配置选项。自动循环完成,在此基础上很容易点击翻页。给按钮一个点击事件。如果在右边,则调用next()方法,否则调用prev()方法。然而,我在这里没有这样做,因为我决定使用事件代理来做,考虑到我们稍后必须做手势(鼠标)来拖动和翻页。让所有事件冒泡到包装容器中也是提高性能的常用技巧之一。
fn . BindEvents=function(){ if(device . desktop){ this . container . addEventlistener(' mouse down ',this,false);this . container . addeventlistener(' mouse move ',this,false);document . addeventlistener(' mouse up ',this,false);} else { this . container . addeventlistener(' touch start ',this,false);this . container . addeventlistener(' touch move ',this,false);document . addeventlistener(' touch end ',this,false);} this . container . addeventlistener(' transitionend ',this,false);this . container . addeventlistener(' click ',this,false);}为什么这里的addEventListener绑定的是这个而不是一个函数?简单来说,就是因为上下文中有一个handleEvent方法,可以被监听函数自动捕获。这个函数名是固定的,不懂可以自己搜索这个函数名。
fn . handleevent=function(e){ var type=e . type;Br//注意这个br}这样做的好处是可以维护事件绑定的函数的上下文。简单来说,不用担心这个方向会变。
完成这一步后,您可以拖动和翻页。在电脑上用鼠标,在手机上用手指,处理方法是一样的,监测按压、移动、释放三个事件。按下时,记住初始坐标,移动时与该坐标进行比较,计算移动距离,然后更新为移动对象(红框)。这里有几个地方需要注意:
1.如果移动时不是直线,x坐标和y坐标都发生变化,判断是水平拖动还是垂直拖动?
2.在pc上,如何判断是拖动还是拖出屏幕?
3.怎么做反弹?
对于第一点,我们可以比较两个方向的距离,以及谁听谁的。如果指向水平滚动,垂直方向的变化可以直接忽略。
对于第二点,可以把监控鼠标放在文档上,最好加上移动距离的判断。如果超过容器的大小,将被视为释放,反弹的反弹,滑动的滑动。
至于第三点,释放拖拽时,判断移动距离。比如拖动距离小于屏幕宽度的1/3,就回去反方向平移对应的距离,甚至不在乎这个距离。反正现在不更新activeIndex,直接返回到这个activeIndex对应的页面会被弹回。这是代码:
fn . stop=function(){ this . axis . x=0;translate3d(this.wrap,this . slide width * this . active index);过渡(this.wrap,this . params . speed);}下一步是制作页码指示器。这很简单。翻页成功后只需更新对应的点即可。因为我们人为插入两页,索引号和页码不能对应。滚动实际涉及6张图片,但只能显示4个点。我做的时候走了一些弯路,但现在无非是两点:
1.给点添加一个属性来标记它是哪一页。用来知道点击和滚动时跳转到哪个页面。
2.使用数组保存页面索引,如[3,0,1,2,3,1],以便在自动翻页或拖动时,可以通过activeIndex的值确定突出显示哪个页面指示器。(小圆点)
或许有更好的办法。暂时就这么办吧。先做功能,有时间有灵感再优化。
这里已经写完了几本书,但是一些边缘情况还需要改进,比如没有图片的情况,默认参数的处理。
想
除了这个还有别的解决办法吗?比如下图,红框里只放了三张图片,多余的叠在屏幕后面。动的时候,不是红盒子,是真的动图?
这个方法可以用,但是我试了一下,发现这个方法在手机上有点卡,在电脑上看的时候容器框会闪,所以没有深入。
咳嗽!咳,下载源代码,请到全球最大的同性交友网站github.com,预览无图在线版
综上
这时主体的逻辑差不多实现了,只用了300行左右的代码。虽然很简洁,但是这里还是有很多东西没有考虑到,比如垂直滚动,兼容性问题等等。通过写生帮助理清思路,遇到困难可以借鉴别人的实现方法,参考但不要原封不动的复制粘贴。代码组织应该考虑可扩展性和可读性,从程序的骨架开始,然后编写处理细节的方法。通过动手实践,我们可以发现一些看似简单的事情,其实并没有那么容易做到。你自己做出来之后,看看别人写的好代码,你就知道别人有什么比我做得更好的地方,有什么值得学习的地方。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。