DDR爱好者之家 Design By 杰米

现在很多javascript的插件都可以实现图片轮播的功能,这篇文章,主要是通过这个domo来解析javascript图片轮播的原理。
老规矩,先上代码。至于代码中的图片,随便找三张即可,最核心的还是理解其思想。

html:

<!DOCTYPE html> 
<html> 
 <head> 
 <meta charset="utf-8" /> 
 <title>滚动图</title> 
 <link rel="stylesheet" type="text/css" href="css/scroll.css"/> 
 </head> 
 <body> 
 <div id="wrapper"> 
  <div id="box"> 
  <img src="/UploadFiles/2021-04-02/banner0.png">

css:

*{ 
 margin: 0; 
 padding: 0; 
} 
#wrapper{ 
 position: relative; 
 width: 1200px; 
 margin: 50px auto; 
 overflow: hidden; 
} 
#pointer{ 
 clear: both; 
 position: absolute; 
 right: 500px; 
 bottom: 15px; 
 width: 180px; 
 height: 2px; 
} 
#pointer span{ 
 display: block; 
 box-sizing: border-box; 
 float: left; 
 width: 50px; 
 height: 1.5px; 
 margin-right: 10px; 
 border-radius: .5px; 
 background: #fff; 
 opacity: .5; 
 -webkit-opacity: .5; 
 -moz-opacity: .5; 
 filter:alpha(opacity=50); 
} 
#pointer .active{ 
 opacity: .8; 
 -webkit-opacity: .8; 
 -moz-opacity: .8; 
 filter:alpha(opacity=80); 
} 
#box{ 
 position: relative; 
 width: 3600px; 
 clear: both; 
} 
img{ 
 display: block; 
 float: left; 
 width: 1200px; 
 height: 337px; 
} 

javascript:

window.onload = function(){ 
 //获取装图片的盒子 
 var box = document.getElementById('box'); 
 //获取装页码的盒子 
 var pointer = document.getElementById('pointer'); 
 //获取盒子中的所有图片 
 var imglist = box.getElementsByTagName('img') 
 //获取盒子中的所有页码 
 var pointerList = pointer.getElementsByTagName('span'); 
 //图片的宽度,正负用于左右的循环 
 var n = -1200; 
 //增加一倍的图片用于循环 
 box.innerHTML = box.innerHTML+box.innerHTML; 
 //设置盒子的宽 
 box.style.width = imglist[0].offsetWidth*imglist.length+"px"; 
 var timer = null; 
 timer = setInterval(function(){ 
 scroll(box,n,pointerList); 
 },3000); 
 box.onmouseover = function(){ 
 clearInterval(timer); 
 } 
 pointer.onmouseover = function(){ 
 clearInterval(timer); 
 } 
 box.onmouseout = function(){ 
 timer = setInterval(function (){ 
//  console.log(new Date()); 
  scroll(box,n,pointerList); 
 },3000); 
 } 
 //设置页码的点击事件 
 for(var i=0;i<pointerList.length;i++){ 
 pointerList[i].index=i;//设置一个参数,用下面调用某个页码 
 //如果不设置参数,在调用页码的时候会直接调用最后一个,因为我们使用了循环 
 pointerList[i].onclick=function (){ 
  for(var j=0;j<pointerList.length;j++){ 
  pointerList[j].className='';//清空激活的class 
  } 
  move(box,n*(this.index));//移动图片 
  this.className='active';//激活点击的页码 
 } 
 } 
 
} 
/** 
 * 循环滚动函数 
 * @param {Object} box 
 * @param {Object} n 
 */ 
function scroll(box,n,page){ 
 //判断是否到达临界点,即box的中间部分 
 if(box.offsetLeft<=-box.offsetWidth/2){ 
 box.style.left = "0px";//重新从头开始 
 console.log('0'); 
 } 
 if(box.offsetLeft%n!=0){ 
 //因为在我们切换浏览器标签页或者切换去其他软件界面的时候, 
 //会影响到setInterval,有时候setInterval会增加好几秒,在这里我们必须加一个判断 
 //只有当它走完了一个整个的图片宽度时,我们才进行下一次滚动。 
 } 
 else{ 
 pageScroll(box,n,page); 
 move(box,n+box.offsetLeft); 
 } 
} 
/** 
 * 滚动页码函数 
 * @param {Object} box 
 * @param {Object} n 
 * @param {Object} page 
 */ 
function pageScroll(box,n,page){ 
 //直接通过图片盒子的定位判断页码值,但是此时的页码值是滚动之前的,所以后面的值要+1使用 
 var index = Math.abs(box.offsetLeft/n); 
 console.log(index); 
 for(var i=0;i<page.length;i++){ 
 page[i].className=''; 
 } 
 //判断是不是最后一页,是最后一页的话+1要变成0; 
 if(index<page.length-1){ 
 page[index+1].className='active'; 
 } 
 else{ 
 page[0].className='active'; 
 } 
} 
 
/** 
 * 变速移动 
 * @param {Object} ele 
 * @param {Object} target 
 */ 
function move(ele,target){ 
 clearInterval(ele.timer); 
 console.log(new Date()); 
 ele.timer = setInterval(function () { 
 var step = (target-ele.offsetLeft)/10; 
 step = step>0"px"; 
 } 
 },30); 
} 

html和css部分依旧比较简单,直接跳过。javascript部分的代码注释写的也比较详细,下面主要讲解逻辑部分。
图片滚动的原理是利用setInterval函数进行背景图片的不断循环。为了避免图片循环的过程中出现间断,首先是在javascript中进行图片的复制(增加一倍),然后当到达临界点时,瞬间将图片移动到初始的位置,然后开始下一轮循环。
在这个domo中,主要包含四个函数:

1、外层控制间隔时间的函数。这个比较容易理解,通过setInterval函数每隔几秒循环执行一次图片滚动的函数。
2、中间层滚动函数。判断图片盒子是否到达临界点,判断当前状态是否符合进入下一次滚动(这个条件主要是为了防止切换界面对setInterval函数的影响,具体原因在最后)。
3、中间层页码滚动函数。基本没有难点,主要是理解页码为什么+1即可。
4、图片滚动函数。这个在之前写过的一篇文章有详细讲解,不再赘述,参考:https://www.jb51.net/article/95211.htm

最后,一点关于setInterval底层机制的扩展。

我们内层函数的执行事件正常情况下为1-2s(测试过),而外层的循环需要3s才进行一次,正常的情况是没有问题的。但是,当你切换界面的时候,浏览器就会对setInterval函数产生影响,此时执行事件的事件就会超过3面,在没移动结束的情况下开启另一个定时器进行下一次图片滚动,所以就会发生错乱。

javascript是单线程的,当你使用setInterval函数的时候并不是真正暂停,而是先挂起这个事件,继续执行下面的事件,而当这个事件要执行时,如果浏览器当前没有任务,那么它会立马执行,但是如果浏览器有任务,那么就会有一定的延迟,这也是为什么切换界面会对setInterval函数的时间产生影响。

(关于setInterval函数的理解如有错误,欢迎指正!如果大家想要深入理解,也可以去一些大神的博客看一下setInterval函数的文章)

精彩专题分享:jQuery图片轮播 JavaScript图片轮播 Bootstrap图片轮播

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

P70系列延期,华为新旗舰将在下月发布

3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。

而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?

根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。