原生JS实现轮播图

迈不过友情╰ 2022-06-08 23:06 463阅读 0赞

原生JS实现轮播图

js实现轮播图,我经历了一下几个步骤:

  1. 把静态界面写出来
  2. 添加切换上一张下一张的箭头(为了省事,直接用的<>…)
  3. 通过调用setTimeOut,让图片动起来,实现轮播的效果
  4. 给每张图片绑定按钮,在鼠标移到相对应的数字时,就会切换到对应的图片
  5. 写博客总结一哈

先上效果图:

静态页面

静态页面的话没什么好说的,其实就是就是加了几张图片,然后修改了一下样式而已。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <style> * { padding: 0px; margin: 0px; } ul { list-style-type: none; } li { float: left; } a { text-decoration: none; font-size: 50px; color: gray; position: absolute; top: 50%; } #prev { left: 0px; } #next { right: 0px; } .container { position: relative; margin: 10px auto; width: 375px; height: 525px; } .list { position: relative; width: 400px; height: 523px; border: 1px solid sienna; overflow: hidden; cursor: pointer; } .list ul { width:5000px; position: absolute; } .list ul li { display: inline; } .count { position: absolute; bottom: 10px; right: 0px; } .count li { float: left; text-align: center; font: 20px Arial; color: white; width: 20px; height: 20px; opacity: 0.7; margin-right: 10px; background: #f90; border-radius: 20px; cursor: pointer; } .count .current { opacity: 1; } </style>
  9. </head>
  10. <body>
  11. <div class="container">
  12. <div class="list">
  13. <ul>
  14. <li><img src="img/乔巴.jpg" alt="乔巴" width="400" height="523"></li>
  15. <li><img src="img/路飞.jpg" alt="路飞" width="400" height="523"></li>
  16. <li><img src="img/山治.jpg" alt="山治" width="400" height="523"></li>
  17. <li><img src="img/索隆.jpg" alt="索隆" width="400" height="523"></li>
  18. <li><img src="img/娜美.jpg" alt="娜美" width="400" height="523"></li>
  19. <li><img src="img/罗宾.jpg" alt="罗宾" width="400" height="523"></li>
  20. <li><img src="img/乔巴.jpg" alt="乔巴" width="400" height="523"></li>
  21. <li><img src="img/路飞.jpg" alt="路飞" width="400" height="523"></li>
  22. </ul>
  23. <ul class="count">
  24. <li>1</li>
  25. <li>2</li>
  26. <li>3</li>
  27. <li>4</li>
  28. <li>5</li>
  29. <li>6</li>
  30. </ul>
  31. <a href="javascript:prev();" id="prev" class="arrow"><</a>
  32. <a href="javascript:next();" id="next" class="arrow">></a>
  33. </div>
  34. </div>
  35. <script src="js/carousel.js"></script>
  36. </body>
  37. </html>

需要注意的是,在图片列表中,第一张和最后一张图片重复添加了,这是为了实现图片之间的带动画效果的无缝切换,后面会讲。

添加箭头

我这里为了省事,直接使用的<>,所以看起来可能不是那么的好看…

最初的计划只是让这两个箭头实现图片的切换,所以写起来就很简单了,只需要在点击箭头时,修改图片的位置就可以了,由于图片的位置使用的是绝对布局,所以位置的改变也是相当方便.

  1. function prev() {
  2. if(imgList.offsetLeft >= 0) {
  3. return;
  4. }
  5. imgList.style.left = imgList.offsetLeft + 400 + 'px';
  6. }

添加动画效果

最初的版本,只是让图片每隔2.5s移动一下,后面由于需要加上与图片关联的按钮,增加了传入的参数,来方便定位到目标图片的位置。

  1. function movToRight(jmpNum) {
  2. jmpNum = jmpNum ? jmpNum : 1;
  3. if(imgList.offsetLeft <= -400*7) {
  4. clearInterval(id);
  5. imgList.style.left = "-400px";
  6. id = setInterval(movToRight, 2500);
  7. }
  8. //console.log(imgList.offsetLeft);
  9. for(let i = 0; i < 40*jmpNum; i++) {
  10. setTimeout(function() {
  11. imgList.style.left = imgList.offsetLeft - 10 + 'px';
  12. //console.log(i);
  13. },i*10/jmpNum);
  14. }
  15. }

最开始还有一个判断,当到达整个图片列表的尾部时,就会清除定时器,然后切换回第一张图片,重新开始轮播。第一次的轮播在页面初始化的时候就已经开始了。

当到达最后一张图片,如果直接切换回第一张图片,那么是没有动画效果的,所以为了实现这种动画效果,又在最后重复添加了第一张图片,这样就能无缝实现从最后一张到第一张的切换。第一张之前添加的那张图片也是这个原因。

将图片和按钮绑定

这个是为了实现图片的快速切换,当鼠标移到数字之上,就会切换到对应的图片。

其实就是向数字上添加了onmouseover事件,当鼠标移动到数字上的时候,判断当前图片和目标图片的距离,然后根据相对的位置,决定向左移还是向右移。

  1. function bindNumWithImg() {
  2. for(let i = 0; i < numList.length; i++) {
  3. numList[i].onmouseover = function() {
  4. this.className = "current";
  5. console.log(this);
  6. var currImg = -imgList.offsetLeft/400 - 1;
  7. var diffVal = i - currImg;
  8. if(diffVal >= 0) {
  9. movToRight(diffVal);
  10. } else {
  11. movToLeft(-diffVal);
  12. }
  13. }
  14. numList[i].onmouseleave = function() {
  15. this.className = "";
  16. }
  17. }
  18. }

总结

整个轮播图实现下来,代码并不多,不过80行左右,不过却让我对于js中的setTimeOut和setInterval这两个方法有了更深的理解。对于这两个方法,我原来用的并不多,或者说几乎没有用过,经过查阅一些资料,也借着这两个方法了解到了JS中的事件队列。JS的执行顺序是由浏览器进行控制的,在页面载入时,首先会对script标签下的代码,通常是一些变量和方法的声明,以及一些初始数据的处理。然后JS进程将等待更多代码的执行,进入空闲。进入空闲后,下一段代码会立即执行。下一段代码的位置就是事件处理队列。就比如说一个onclick方法,当点击那个绑定onclick的元素后,会立即把对应的方法加入到事件处理队列中去,但是不会立即执行,而是等到JS进程空闲时,才会执行代码。

setTimeOut也是这样的,只会在你设定的时间之后添加到事件处理队列中去,但并不一定会立即执行。

在使用setTimeOut时需要注意的是,传入的第一个参数,要么是一个方法,要么是一个代码段,注意,这个代码段是要加引号的,虽然在浏览器中不会报错,但是会立即执行。在node中会报错,指出传入参数不正确。

在实现的过程中,有一个问题困扰了我好久,就是实现的动画效果有些问题,在进行图片切换的时候,会有空白,额说不清楚,上图:

problemExample

后面发现,由于某种原因,在当前图片之后的图片会到下一行,当然了,解决这个问题很简单,设置这一行的宽度很宽就行了,这里换行的原因是,由于是浮动元素,在排列时需要判断最右的边界,默认情况下,浮动元素是不能超过边界的,所以他就会自动的换行了。但是那些浮动的元素却可以到前面去,这是因为通过left改变了它的左边界。
最终效果图:
这里写图片描述

下面是完整的JS代码:

  1. var list = document.getElementsByClassName("list")[0];
  2. var imgList = list.getElementsByTagName('ul')[0];
  3. var imgs = imgList.getElementsByTagName("li");
  4. var numList = list.getElementsByClassName("count")[0].getElementsByTagName('li');
  5. var id;//setInterval 的id
  6. function init() {
  7. imgList.style.left = "-400px";
  8. list.onmouseover = function() {
  9. clearInterval(id);
  10. }
  11. list.onmouseout = function() {
  12. id = setInterval(movToRight, 2500);
  13. }
  14. autoPlay();
  15. bindNumWithImg();
  16. }
  17. function bindNumWithImg() {
  18. for(let i = 0; i < numList.length; i++) {
  19. numList[i].onmouseover = function() {
  20. this.className = "current";
  21. console.log(this);
  22. var currImg = -imgList.offsetLeft/400 - 1;
  23. var diffVal = i - currImg;
  24. if(diffVal >= 0) {
  25. movToRight(diffVal);
  26. } else {
  27. movToLeft(-diffVal);
  28. }
  29. }
  30. numList[i].onmouseleave = function() {
  31. this.className = "";
  32. }
  33. }
  34. }
  35. function next() {
  36. movToRight();
  37. }
  38. function prev() {
  39. movToLeft();
  40. }
  41. //使得图片向左播放
  42. function movToLeft(jmpNum) {
  43. jmpNum = jmpNum ? jmpNum : 1;
  44. if(imgList.offsetLeft >= 0) {
  45. imgList.style.left = "-2400px";
  46. }
  47. for(let i = 0; i < 40 * jmpNum; i++) {
  48. setTimeout(function() {
  49. imgList.style.left = imgList.offsetLeft + 10 + 'px';
  50. }, i*10/jmpNum);
  51. }
  52. }
  53. //使得图片向右播放
  54. function movToRight(jmpNum) {
  55. jmpNum = jmpNum ? jmpNum : 1;
  56. if(imgList.offsetLeft <= -400*7) {
  57. clearInterval(id);
  58. imgList.style.left = "-400px";
  59. id = setInterval(movToRight, 2500);
  60. }
  61. //console.log(imgList.offsetLeft);
  62. for(let i = 0; i < 40*jmpNum; i++) {
  63. setTimeout(function() {
  64. imgList.style.left = imgList.offsetLeft - 10 + 'px';
  65. //console.log(i);
  66. },i*10/jmpNum);
  67. }
  68. }
  69. function autoPlay() {
  70. id = setInterval(movToRight, 2500);
  71. }
  72. init();

其中的方法的设计可能有些不足,还请多多指点。

发表评论

表情:
评论列表 (有 0 条评论,463人围观)

还没有评论,来说两句吧...

相关阅读

    相关 原生js实现

            很多很多网站经常会用到一个特效,那就是轮播图,对于日新月异的前端技术来说其实就是一个框架一个接口的事,但轮播的原理是什么?用最原始的javascript来写又是

    相关 原生js实现

    轮播图基本上是前端所必须面临的一个功能。而且在网上可以找到各种各样的插件或者写法。 但是我个人觉得还是写一下比较好。这里用到的是原生JS、CSS3相结合的写法。 对IE 8

    相关 原生js实现

    原生js实现轮播图  很多网站上都有轮播图,但却很难找到一个系统讲解的,因此这里做一个简单的介绍,希望大家都能有所收获,如果有哪些不正确的地方,希望大家可以指出。  [