一直想自己动手做一个图片轮播的控件,查查网上的资料大多引用已经做好的组件,其原理算法不是很清楚,于是自己用jquery写了一个.先看下效果图:
主要界面实现思路如下:
1.新建一个div宽度为100%,flex布局,主要是为了网页主体内容居中,和留白部分的进一步处理
2.新建div,为网页的内容宽度,设置为1200px
3.图片轮播窗口,宽度,高度为300px,overflow:hidden
4.轮播窗口新建ul>li>img,ul采用position:relative
5.li样式 border-radius:150px主要是制作圆形视图
6.同ul同级,新建div>span 当前图片页码,position:relative,span border-radius:10px,圆形
7.将当前图片页码定位到图片视窗内
图片轮播设计思路:
1.在录播窗口以jq动画 animate移动ul
2.在ul的起始位置插入(insertBefore)最后一个元素的clone,$('ul li:nth-child(7)').clone(),在ul的最后一个追加(insetAfter)
第一个元素$('ul li:nth-child(7)').clone(),这时比如,list中有7个元素,经过追加之后,有9个元素,(这么做主要是为了ul在向左或
者向右移动之后,视觉上一连续切换到最后一个,或者第一个)
3.点击向左/向右,向左向右每次移动一个img的宽度(300px)
3.如果当前展示的img是第一个,再向左移动一个,连续展示我们插入的最后一个元素,然后迅速将ul定位到img的倒数第二个元素,反之定位到第二
个元素,这样就实现了一个循环轮播
4.最后设置,展示的图片和图片页码对应的样式
5.设计逻辑,比如点击了向左,每隔5秒自动播放的时候,也是向左播放,页码切换的时候是向左切换,自动播放也将切到向左,反之亦然
下面是页面代码:
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <title>图片轮播</title> <script src="./javascript/jquery.min.js"></script> <style type="text/css"> * { text-decoration: none; list-style: none; margin: 0; padding: 0; font-size: 14px; letter-spacing: 1px; color: #000; background: none; } .window-content ul { width: 5000px; display: flex; text-wrap: none; white-space: nowrap; position: relative; } .window-content ul li div { line-height: 300px; } .window-content ul li { float: left; border-radius: 150px 150px 150px 150px; overflow: hidden; } .window-content { width: 300px; height: 300px; overflow: hidden; background: none; border: 1px solid #ededed; border-radius: 150px; } .window { width: 100%; height: 340px; display: flex; align-items: center; justify-content: center; flex-direction: column; background: #f4f4f4; } .window-wrap { flex: 1; width: 1200px; display: flex; align-items: center; justify-content: center; flex-direction: row; background: #e0e0e0; } .window-index { position: relative; top: -19px; left: 101px; margin: -20px; } .window-index .content-index { text-align: center; line-height: 20px; font-size: 12px; width: 20px; height: 20px; color: black; display: inline-block; border: 1px solid antiquewhite; background: white; margin:-3px; border-radius: 10px; } .window-index .content-index:hover { cursor: pointer; } .selected:hover { cursor: pointer; } .selected { text-align: center; line-height: 20px; font-size: 12px; width: 20px; height: 20px; display: inline-block; border: 1px solid antiquewhite; margin:-3px; border-radius: 10px; background: #9e0909; color: white; } </style> <script> class PicMove { constructor() { //录播图片容器 this._parent = $('.window-content ul'); //容器中图片的起始个数 this._elmentcount = this._parent.children().length; //起始第一个元素 this._head = this._parent.children(':nth-child(1)'); //起始最后一个元素,nth-child下标是从1开始的 this._tail = this._parent.children(':nth-child(' + this._elmentcount + ')'); //当前轮播窗口,图片的下标(页码) this._arrowflag = 1; //播放的方向,默认是向右 this.isRunRight = true; //主要是成员函数中用到了this,为了防止发生异常,对成员函数中的this进行绑定 this.RunLeft = this.RunLeft.bind(this); this.RunRight = this.RunRight.bind(this); this.LeftStop=this.LeftStop.bind(this); this.RightStop=this.RightStop.bind(this); this.Move=this.Move.bind(this); this.autoMove=this.autoMove.bind(this); this.auToRun=this.auToRun.bind(this); this.showIndex=this.showIndex.bind(this); //自动轮播的计时器 this.Interval=null; } //启动自动播放 autoMove() { //启动自动播放之前,清除掉历史的,要不然播放的速度或者次序可能会乱,整个界面只保留一个有效的计时器 if(this.Interval) { clearInterval(this.Interval); } //设置每隔5秒,左播放,或者右播放 this.Interval=setInterval(this.auToRun,5000); } //执行向左或者向右轮播动作 auToRun() { if(this.isRunRight===true) { this._parent.animate({'left': '-=300px'}, 300, ()=>{ //动画执行完成的,回调函数使用箭头函数,主要是里面也有this,并且this期望指向当前类的实例,而不是调用环境,和在构造中bind成员函数的效果是一样的 //页码加 this._arrowflag++; if (this._arrowflag > this._elmentcount) { //右播放到最后一个,应该从第一个开始,所以这里瞬间定位到第二张图片的位置(第一张图片是克隆的最后一站图片),图片都是一样的,感官没有觉察 this._parent.css({'left': '-300px'}); this._arrowflag = 1; } //播放完成设置页码样式 this.showIndex(); }); } else { this._parent.animate({'left': '+=300px'}, 300, ()=>{ this._arrowflag--; if (this._arrowflag < 1) { this._parent.css({'left': -(300 * this._elmentcount) + 'px'}); this._arrowflag = this._elmentcount; } this.showIndex(); }); } } //设置页码样式 showIndex() { $(".selected").removeClass("selected").addClass("content-index"); $(".content-index:nth-child("+ this._arrowflag+")").removeClass("content-index").addClass("selected"); } //页面加载完成初始化,图片轮播控件 init() { this._tail.clone().insertBefore(this._head); this._head.clone().insertAfter(this._tail); //初始定位到this.head元素的位置,这个是起始位置 this._parent.css('left', '-300px'); //向右按钮事件 $('.run-right').click(this.RunRight); $('.run-left').click(this.RunLeft); //页码被hove,时执行的操作 $('.content-index').hover((e)=>{ let thisEle=$(e.target); let index=Number.parseInt(thisEle.html()); //这里,主要是为了测试在鼠标hover的时候,响应函数被执行了几次 //console.log(`${this._arrowflag}-->${index}`); //视窗图片,展示指定页码的图片 this.Move(index); //thisEle.removeClass("content-index") //thisEle.addClass("selected"); this.showIndex(); }); this.showIndex(); this.autoMove(); } //这个函数主要是,向左移动一次之后,回调设置成员的值,设置初始化循环播放 LeftStop() { this._arrowflag--; this.isRunRight = false; if (this._arrowflag < 1) { this._parent.css({'left': -(300 * this._elmentcount) + 'px'}); this._arrowflag = this._elmentcount; } this.showIndex(); this.autoMove(); } //向左按钮事件,函数 RunLeft() { clearInterval(this.Interval); this._parent.stop(true,true); this._parent.animate({'left': '+=300px'}, 300, this.LeftStop) } //这个函数主要是,向右移动一次之后,回调设置成员的值,设置初始化循环播放,由于有this,所以这么定义 RightStop() { this._arrowflag++; this.isRunRight = true; if (this._arrowflag > this._elmentcount) { this._parent.css({'left': '-300px'}); this._arrowflag = 1; } this.autoMove(); this.showIndex(); } //向右按钮事件 RunRight() { clearInterval(this.Interval); //鼠标hover,很快可能定义的动画还没执行完,就开始响应下一次移动,会造成混乱,这里提前结束每个动画,并且停在动画的终点 this._parent.stop(true,true); this._parent.animate({'left': '-=300px'}, 300, this.RightStop) } //页码hover的时候,移动的函数 Move(index) { let current=this._arrowflag; this._arrowflag=index; if (index<current)//左移 { this.isRunRight = false; var count=current-index; this._parent.stop(true,true); this._parent.animate({'left': '+='+(300*count)+'px'}, 300, ()=>{ this.autoMove(); }); this.showIndex(); } else if(index>current)//右移 { this.isRunRight = true; var count=index-current; this._parent.stop(true,true); this._parent.animate({'left': '-='+(300*count)+'px'}, 300, ()=>{ this.autoMove(); this.showIndex(); }); } } } $(function () { //页面加载完成,初始化图片轮播控件 let picmove = new PicMove(); picmove.init(); }); </script> <script src="javascript/jquery.transit.js"></script> </head> <body> <div class="window"> <div class="window-wrap"> <span class="run-left">向左</span> <div class="window-content"> <ul> <li> <div style="background-image: url('./images/show-window/1.jpg');background-size: cover;width: 300px;height: 300px"> 1 </div> </li> <li> <div style="background-image: url('./images/show-window/3.jpg');background-size: cover;width: 300px;height: 300px"> 2 </div> </li> <li> <div style="background-image: url('./images/show-window/4.jpg');background-size: cover;width: 300px;height: 300px"> 3 </div> </li> <li> <div style="background-image: url('./images/show-window/5.jpg');background-size: cover;width: 300px;height: 300px"> 4 </div> </li> <li> <div style="background-image: url('./images/show-window/6.jpg');background-size: cover;width: 300px;height: 300px"> 5 </div> </li> <li> <div style="background-image: url('./images/show-window/7.jpg');background-size: cover;width: 300px;height: 300px"> 6 </div> </li> <li> <div style="background-image: url('./images/show-window/8.jpg');background-size: cover;width: 300px;height: 300px"> 7 </div> </li> </ul> <div class="window-index"> <span class="content-index">1</span> <span class="content-index">2</span> <span class="content-index">3</span> <span class="content-index">4</span> <span class="content-index">5</span> <span class="content-index">6</span> <span class="content-index">7</span> </div> </div> <span class="run-right">向右</span> </div> </div> </body> </html>
才开是学习前端,代码有需要重构的地方,比如页码hover的逻辑,也向左向右按钮的事件代码有重复,自动轮播的时间间隔,可以拎出来单独配置,以后要改时间就改一个变量的值就可以了,flex布局在IE上不支持,没有做浏览器适配等
希望指正!