原理
图片轮播原理:
将一系列大小相等的图片平铺,利用css布局只显示一张图片,其他图片隐藏,通过计算偏移量利用定时器自动切换图片,或者手动点击切换图片。
样式布局
关于图片列表的布局,这里在js中使用style.left
这个属性计算偏移量来进行图片的切换。而在style.left
这个属性中,是无法识别样式表中写的left值,只对HTML中写的left值有效.
关于小圆点按钮,使用自定义属性index
来标识第几个小圆点。后边当点击某个小圆点时,可获取该小圆点的index值来知道小圆点的位置。利用css样式使class="on"
的元素颜色变亮,即点亮当前点击到的小圆点。
关于箭头切换,使用链接形式,可以添加hover
伪类变换样式。<
左箭头;>
右箭头,html转义字符。
无缝切换:最后一张图片切换到第一张图片时,会出现一片空白,这里,借助两张辅助图来填补这片空白。
即将最后一张图片属性复制到第一张图片前,将第一张图片属性信息复制到最后一张图片后面。
并且,将第一张图片辅助图(实际上是实际显示的第5张图片隐藏起来,故设置style="left: -600px;"
)
css结构:
- 绝对定位问题,图片和原点的浮动属性;
-
overflow: hidden;
//溢出隐藏 - 确保每个小圆点所在层置顶,(z-index:999;)这里设置为
z-index:2; 另外
z-index 仅能在定位元素上奏效 -
cursor
CSS属性定义鼠标指针悬浮在元素上方显示的鼠标光标。cursor: pointer
显示为小手。
*{
margin: 0;
padding: 0;
text-decoration: none;
}
body{
padding: 10px;
}
#container{
width: 600px;
height: 400px;
border: 3px solid #333;
overflow: hidden;//溢出隐藏
position: relative;//定位
}
#list{
width: 4200px;//所有图片平铺的宽度
height: 400px;
border: 3px solid #333;
position: absolute;//定位问题 利用偏移量进行切换
/*z-index: 1;*/
/* transition:left 2s;
-moz-transition:left 2s; Firefox 4
-webkit-transition:left 2s; Safari and Chrome
-o-transition:left 2s; Opera */
}
#list img{
float: left;//浮动(不用清除浮动)
}
#buttons{
position: absolute;
/*height: 20px;
width: 100px*/
/*z-index: 2;*/ //层级,使按钮置于顶层
bottom: 25px;
left: 250px;
}
#buttons span{
cursor: pointer;/*小手*/
float: left;//浮动
border: 1px solid #fff;//白边框
width: 20px;
height: 20px;
border-radius: 50%;//圆角
background: #333;//黑色
margin-right: 5px;
}
#buttons .on{
background: orangered;//点亮成橘色
}
.arrow{
cursor: pointer;
display: none;//默认不显示箭头
line-height: 39px;//垂直居中
text-align: center;//水平居中
font-size: 36px;
font-weight: bold;
width: 40px;
height: 40px;
position: absolute;//绝对定位
/*z-index: 2;*/
top: 180px;//高度
background-color: rgba(0,0,0,0.3);
color: #fff;
}
.arrow:hover{
background-color: rgba(0,0,0,0.7);//鼠标移上去颜色加深
}
#container:hover .arrow{
display: block;//鼠标移到盒子上显示箭头
}
#prev{
left: 20px;//单独定义左箭头水平位置
}
#next{
right: 20px;//单独定义右箭头水平位置
}
js部分整个功能封装在window.onload
事件中。
箭头切换&无限滚动&动画切换
先获取元素,添加点击事件。parseInt
将字符串转换成数字。
获取style.left
,是相对左边获取距离,且style.left
获取的是字符串,需要用parseInt()取整转化为数字。
next.onclick=function(){
list.style.left=parseInt(list.style.left)-600+'px';
}
prev.onclick=function(){
list.style.left=parseInt(list.style.left)+600+'px';
}
封装在函数animate
里。并实现循环切换。当切换到第一张辅助图上时,parseInt(list.style.left)
的值为0,实际上应该是最后一张图片,所以归为到最后一张图片的位置上list.style.left=-3000+'px';
同理,当切换到第二张辅助图上时,parseInt(list.style.left)
的值为-3600,实际上应该是第一张图片,所以归为到第一张图片的位置上list.style.left=-600+'px';
//切换图片,利用图片的偏移量
function animate(offset){
var newLeft = parseInt(list.style.left)+offset;//值 图片左侧距离父元素的值
list.style.left=newLeft+'px';//px
// list.style.left=list.offsetLeft+offset+'px';
if(newLeft>-600){//和第一张图片位置比较
list.style.left=-3000+'px';//归位到第五张图片
}
if(newLeft<-3000){//和最后一张图片位置比较
list.style.left=-600+'px';//归位到第一张图片
}
// debugger;
}
实现每次切换图片的过程中,是过渡动画切换的。
思路:通过自定义位移完一张图片的总时间time
和每次位移的时间inteval
,来计算图片移动一下的距离speed
,直到一张图片完整的移到当前可视的盒子区域。
在animate()
函数内定义go()
函数,首先判断图片是往哪个方向移,因为如果向左移的话,即传入的偏移量是负值,所以speed < 0
,这时候图片左侧距离父元素的值parseInt(list.style.left)
是越来越小的,直到为newLeft
,结束动画位移,一张图片完整的切换到了可视区域。so只要parseInt(list.style.left) >newLeft
,就进行动画位移;
同理,当图片向右移时,speed >0
,这时候图片左侧距离父元素的值parseInt(list.style.left)
是越来越大的,直到为newLeft
。所以只要parseInt(list.style.left) < newLeft
,就进行着动画位移。
如果满足动画位移条件会一直执行,使用定时器setTimeout(go, inteval)
,没隔一段时间interval
执行一次go
。
这里使用了递归,函数内部调用该函数。
对于定时器,注意setInterval()跟setTimeout()的区别。简单来说,setInterval()执行多次,setTimeout()只执行一次。
更具体的用法可以点击链接查看区别:window.setInterval window.setTimeout 。
这里定义一个初始值var animated = false;
,表示默认不进行动画位移,animated = true
表示开始动画位置标志。并在结束动画位移操作时,将animated
的值置为false。
function animate (offset) {
animated = true;//开始动画位移
var time = 300;//一张图片位移总时间
var inteval = 10;//位移间隔时间
var speed = offset/(time/inteval);//求得一次位移的距离
var newLeft = parseInt(list.style.left) + offset;//图片左侧距离父元素的值
//动画函数
var go = function (){
//监测是否具备进行动画位移的条件
//判断左切换和右切换两种情况,都并且一张图片没有完整的占满盒子区域时。
if ( (speed > 0 && parseInt(list.style.left) < newLeft) || (speed < 0 && parseInt(list.style.left) >newLeft)) {
list.style.left = parseInt(list.style.left) + speed + 'px';
setTimeout(go, inteval);//递归
}else {
list.style.left = newLeft + 'px';
if(newLeft>-600){
list.style.left=-3000+'px';//归位到第五张图片
}
if(newLeft<-3000){
list.style.left=-600+'px';//归位到第一张图片
}
// debugger;
animated = false;//结束动画位移
}
}
go();//函数调用
}
优化:加入下面代码,当传入的偏移量为0时,animate()函数里面的部分不需再执行了。
if (offset == 0) {
return;
}
按钮切换
先设置初始值index
的值为1.即默认第一个小圆点时点亮着的,index
用来标识第几个小圆点。点击箭头时增加或者减小index
的值来实现切换小圆点的功能。注意index的取值是1~5,所以当index的值加到5时,要回归到1;index的值为1时,要切到5.
实现思路:先判断index的值,右箭头触发点击事件里如果当前index的值为5,就使index=1
,否则index+=1;
,同理,左箭头触发点击事件里如果当前index的值为1,就使index=5
,否则index-=1;
然后点亮相应的小圆点showButton()
var index = 1;
next.onclick=function(){
animate(-600);
if(index==5){
index=1;//使index的值不超过5
}else{
index+=1;//index的值随着箭头的点击进行更新
}
showButton();
}
prev.onclick=function(){
animate(600);
if(index==1){
index=5;//使index的值不小于1
}else{
index-=1;
}
showButton();
}
优化:在两个点击事件中先加入以下代码。当检测到animated=true
即进行着动画位移,不执行其他代码,避免卡顿优化性能。
if (animated) {
return;
}
获取小圆点var buttons = document.getElementById('buttons').getElementsByTagName('span');
,不止一个,是一个数组类型。数组从0开始,所以index -1
.
因为css样式中#buttons .on{background: orangered;}
,所以这里利用className= 'on'
来点亮小圆点。
//点亮小圆点
function showButton(){
buttons[index -1].className = 'on';//点亮
}
这样会出现一个问题,切换到下一个小圆点时,前面点击过的小圆点依然是点亮着的。所有在showButton()
函数中要先清除之前的样式。
for(var i=0;i
这样就实现了点击箭头切换图片时,对应的小圆点也跟着进行切换。
===
下面实现点击小圆点时,图片切换的功能
(思路:仍然是利用图片偏移量进行切换,偏移值为-600乘以要点击的小圆点的index值减去当前小圆点的index值)
因为要对每一个小圆点添加点击事件,先对其进行遍历。
首先获取要点击的(目标)小圆点的自定义属性值parseInt(this.getAttribute('index'))
,即在html布局中span标签里index的属性。
getAttribute()
既可以获取自定义属性值也可以获取原本就存在的属性的值。
不要忘记更新当前的index值index=myIndex;
//点击小圆点进行切换图片
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function(){//对每个小圆点添加点击事件
var myIndex = parseInt(this.getAttribute('index'));//获取要点击的小圆点的自定义index属性值
console.log(myIndex);
var offset = -600*(myIndex-index);//求偏移值
animate(offset);
index=myIndex;//更新到当前的index值
showButton();
}
// debugger;
}
优化:在每个小圆点的点击事件中加入以下代码。
点击小圆点时,当检测到animated=true
即进行动画位移的过程中,不触发该点击事件即不执行后面代码,避免卡顿优化性能。
当检测到this.className=='on'
即点击当前的小圆点,也不需要执行后面代码,优化性能。
if (animated) {
return;
}
if(this.className=='on'){
return;
}
自动播放
利用定时器setTimeout()
或setInterval
,实现每隔3秒自动播放下一张图片。并在鼠标移到var container = document.getElementById('container');
上时清楚浮动。
用到一种回调函数的使用方式,如果stop(),stop方法就被执行了,但是如果写方法名stop,是事件触发时才会调用stop方法
var interval = 3000;
var timer;
function play() {
timer = setTimeout(function () {
next.onclick();
play();
}, interval);
}
function stop() {
clearTimeout(timer);
}
/*
//每隔3秒自动播放下一张图片
function play(){
timer = setInterval(function(){
next.onclick();
},3000);
}
//清除定时器
function stop(){
clearInterval(timer);
}
*/
container.onmouseover = stop;
container.onmouseout = play;
play();
最后,如果不进行一些优化,可能会出现疯狂点击会使图片错位等情况。