服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - js教程 - JavaScript Dom实现轮播图原理和实例

JavaScript Dom实现轮播图原理和实例

2022-01-21 15:29ALonelyLemon js教程

这篇文章主要为大家详细介绍了JavaScript Dom实现轮播图原理和实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

想要制作一个轮播图我们要先弄清楚他的原理,如何能让图片自右向左滑动?
让我们想一想生活中有没有类似的东西,比如电影胶片。
我们可以创建一个块作为投影区,创建一个列表作为底片并使其向左移动,达到轮播图效果。

JavaScript Dom实现轮播图原理和实例

创建一个块和列表

创建一个块作为总的容器和显示区域。

?
1
2
3
4
5
6
7
8
<div id="out">
 <ul id="imgList">
 <li><img src="pto/many.jpg" ></li>
 <li><img src="pto/hello.jpg" ></li>
 <li><img src="pto/timg.jpg" ></li>
 <li><img src="pto/zhenjing.jpg"></li>
 </ul>
</div>

现在图片竖着堆在一列,块也不知道在哪里,那添加一点样式

开启定位并令其居中,并且让块大一点并添加背景好确定位置(本实验图片统一宽高比500*431,所以div宽高比520*451)

去掉列表默认样式让列表横着显示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
*{
 margin: 0;
 padding: 0;
 }
 #out{
  width:520px;
  height:451px ;
  background-color: #00bcd4;
 position: relative;
 margin: 50px auto;
 /*overflow: hidden;*/
 /*剪掉我们不需要的部分,为了方便调试注掉了*/
 }
 
 #imgList{
  list-style: none;
  position: absolute;
  /* left: -520px; */
 }
 #imgList li{
  float:left;
  margin: 10px;
}

在尝试浮动后图片依旧是一列,是因为lu的宽度太小放不下,所以我们要扩大,但是我们不能直接决定他的宽度因为随着图片的增加,宽度应不断变大,于是我们用JavaScript来解决宽度
每增加一张图片扩大520px宽度

?
1
2
3
4
5
6
window.onload=function () {
 // 动态的ul长度
 var imgList = document.getElementById("imgList");
 var imgArr = document.getElementsByTagName("img");
 imgList.style.width=520*imgArr.length+"px";
 }//onload

现在,装载图片的胶片ul每向左偏移-520px就会更换一个图片

导航栏

轮播图会定时更换,但是有可能你的客户刚刚被吸引就已经更换图片了,如果你想让你的客户干巴巴的瞪着图片回来,你很可能失去她。
所以一个完整的轮播图还需要一个能手动切换前后的按钮或一个导航条。
我们这里用几个超链接完成任务

?
1
2
3
4
5
6
<div id="navDiv">
 <a href="javascript:;"></a>
 <a href="javascript:;"></a>
 <a href="javascript:;"></a>
 <a href="javascript:;"></a>
</div>

ul在开启绝对定位后脱离文档流,现在我们的导航因为没有内容缩成一团挤在左上角
我们要让每一个超联接彼此分开,手动撑开空间,调整到靠下的位置,下方正中或靠右是比较好的选择.
调整透明度降低导航对于人的吸引力,毕竟图片才是主题。
而位置的调整为了便于扩充我们还是要用js来解决。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
}
#navDiv{
 position: absolute;
 bottom: 15px;
}
#navDiv a{
 float: left;
 width: 15px;
 height: 15px;
 background-color: #89ff00;
 margin: 0 5px;
 opacity: 0.5;
}
?
1
2
3
4
5
6
7
8
//动态导航居中
 var navDiv = document.getElementById("navDiv");
 var out = document.getElementById("out");
 
 //将纵向剩余距离分到导航左右达到居中效果
 //不除以二就会变成右对齐
 //不要忘了单位,嗯。。可能只有我会忘吧
 navDiv.style.left = (out.clientWidth - navDiv.clientWidth)/2+"px";

导航功能完善

一仅仅个15px大的方块要给用户怎样的反馈?
当前图片所处位置,当鼠标移动到导航是时要反馈信息告诉用户我是可以点击的,点击导航能切换图片。

?
1
2
3
4
5
#navDiv a:hover{
  background-color: red;
  /* 鼠标移入效果*/
 /* 内联样式的优先级很高注意不要被覆盖失效*/
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//定位效果
var allA = document.getElementsByTagName("a");
var index = 0;
 allA[index].style.backgroundColor="black";
 
 //点击导航效果
 //使用块级作用域let,不然i会是同一个数
 for(let i=0;i<allA.length;i++){
  allA[i].onclick=function () {
  imgList.style.left=-520*i+"px";
 
  //清除内联样式,使得css文件能生效
  allA[index].style.backgroundColor="";
  index=i;
  allA[index].style.backgroundColor="black";
  }
 }

动画效果

为什么要做动画? (因为很酷(≧ω≦*)♪ )

因为没有轮播效果不叫轮播图,明明更改地址就能完成,忙活半天不就是为了这个,用最大的标题告诉你动画才是轮播图的精髓所在

主要思路是利用定时器让本来一部完成的效果多次完成,到达指定位置关闭定时器。

要注意的问题

每次移动距离与图片大小可能除余,导致停止位置不准确(大于或小于)或无法停止(不能刚好到达停止位置),小的误差会逐渐积累。
在定时器打开前关闭上一个计时器,否则在一个动画未完成前点击另一个会发生鬼畜现象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//点击导航效果
 for(let i=0;i<allA.length;i++){
  allA[i].onclick=function () {
  move(imgList,-520*i,10);
  // imgList.style.left=-520*i+"px";
  //换掉这个很low的过场
  allA[index].style.backgroundColor="";
  index=i;
  allA[index].style.backgroundColor="black";
  }
 }
 
function move(obj,target,speed) {//元素;目标位置;速度
  //每次触发事件关闭上一个定时器
  //这里是重点,你可以去掉这一句后随意点一下关差效果
  clearInterval(obj.timer);
  
  var current = parseInt(window.getComputedStyle(obj,null).left);
  //获得当前位置
  //判断运动方向
  if(target<current){
  speed = -speed;
  }
  //定时器标识
  obj.timer = window.setInterval(function () {
  //m每次开始获取一下当前位置
  var oldValue = parseInt(window.getComputedStyle(obj,null).left);
  //移动并在指定位置停下
  var newValue = oldValue + speed;
  //调整一下停止位置,小的误差会随时间无限放大
  if((speed < 0 && newValue < target)||(speed > 0 && newValue > target)){
   newValue = target;
  }
  imgList.style.left =newValue+"px";
  if(newValue == target){
   clearInterval(obj.timer);
  }
 
  },30);
 
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
change();
 //自动轮播
 //一个定时器用于定时调用
 function change() {
  setInterval(function () {
  index++;
  index=index % imgArr.length ;
  console.log(imgArr.length);
  console.log(index);
  move(imgList,-520*index,20);
  for(let i=0;i<allA.length;i++){
   allA[i].style.backgroundColor="";
   allA[index].style.backgroundColor="black";
  }
  },3000);
 }

这样已经能做到轮播的基本功能,但在最后一张图片切换第一张图片时会向左拉过全部图片,这非常的不酷,我们要让轮播图持续向左循环怎么办?

假设我们要对图a和图b两个图轮播

我们可以结尾插入一个与图a一样的图
在两张图轮播完后转入第三张图让人误认为是第一张图片
在第三张图完成轮播后瞬间跳转至第一张继续轮播,此为瞒天过海之计

JavaScript Dom实现轮播图原理和实例

对于轮播图我们其实只需要知道原理,且不说框架,jquery完成轮播图都不要单纯手撸的十分之一的精力。

完整代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style>
 *{
  margin: 0;
  padding: 0;
 }
 #out{
  width:520px;
  height:451px ;
  margin: 50px auto;
  background-color: #00bcd4;
  position: relative;
  overflow: hidden;
 }
 
 #imgList{
  list-style: none;
  position: absolute;
 }
 #imgList li{
  float:left;
  margin: 10px;
 }
 #navDiv{
  position: absolute;
  bottom: 15px;
 }
 #navDiv a{
  float: left;
  width: 15px;
  height: 15px;
  background-color: #89ff00;
  margin: 0 5px;
  opacity: 0.5;
 
 
 }
 #navDiv a:hover{
  background-color: red;
 /* 内联样式的优先级很高在触发一次后覆盖失效*/
 }
 
 </style>
</head>
<body>
<div id="out">
 <ul id="imgList">
 <li><img src="pto/many.jpg" ></li>
 <li><img src="pto/hello.jpg" ></li>
 <li><img src="pto/timg.jpg" ></li>
 <li><img src="pto/zhenjing.jpg"></li>
 <li><img src="pto/many.jpg" ></li>
 </ul>
 <div id="navDiv">
 <a href="javascript:;" ></a>
 <a href="javascript:;" ></a>
 <a href="javascript:;" ></a>
 <a href="javascript:;" ></a>
 </div>
</div>
<script>
 window.onload=function () {
 // 动态的ul长度
 var imgList = document.getElementById("imgList");
 var imgArr = document.getElementsByTagName("img");
 imgList.style.width=520*imgArr.length+"px";
 
 //动态导航居中
 var navDiv = document.getElementById("navDiv");
 var out = document.getElementById("out");
 navDiv.style.left = (out.clientWidth - navDiv.clientWidth)/2+"px";
 
 //定位效果
 var allA = document.getElementsByTagName("a");
 var index = 0;
 allA[index].style.backgroundColor="black";
 
 //点击导航效果
 for(let i=0;i<allA.length;i++){
  allA[i].onclick=function () {
  move(imgList,-520*i,20);
  setA();
  // imgList.style.left=-520*i+"px";
  // allA[index].style.backgroundColor="";
  // index=i;
  // allA[index].style.backgroundColor="black";
  }
 }
 
 // 动画效果
 function move(obj,target,speed,callback) {//元素;目标位置;速度;回调函数
  clearInterval(obj.timer);
  var current = parseInt(window.getComputedStyle(obj,null).left);
  //获得当前位置
  //判断运动方向
  if(target<current){
  speed = -speed;
  }
  //定时器标识
  obj.timer = window.setInterval(function () {
  //m每次开始获取一下位置
  var oldValue = parseInt(window.getComputedStyle(obj,null).left);
  //移动并在指定位置停下
  var newValue = oldValue + speed;
  //调整一下停止位置,小的误差会随时间无限放大
  if((speed < 0 && newValue < target)||(speed > 0 && newValue > target)){
   newValue = target;
  }
  imgList.style.left =newValue+"px";
  if(newValue == target){
   clearInterval(obj.timer);
   callback();
  }
 
  },30);
 
 }
 change();
 //自动轮播
 //一个定时器用于定时调用
 function change() {
  setInterval(function () {
  index++;
  index=index % imgArr.length ;
  move(imgList,-520*index,20,function () {
   if(index>=imgArr.length-1 ){
   imgList.style.left =0;
   }
   setA();
  });
 
  },3000);
 }
 function setA() {
  for(let i=0;i<allA.length;i++){
  allA[i].style.backgroundColor="";
  allA[index].style.backgroundColor="black";
 
  }
 }
 }//onload
</script>
</body>
</html>

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

原文链接:https://blog.csdn.net/lemon_yu/article/details/89303979

延伸 · 阅读

精彩推荐
  • js教程JavaScript Dom实现轮播图原理和实例

    JavaScript Dom实现轮播图原理和实例

    这篇文章主要为大家详细介绍了JavaScript Dom实现轮播图原理和实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    ALonelyLemon3652022-01-21
  • js教程arcgis.js控制地图地体的显示范围超出区域自动弹回(实现思路)

    arcgis.js控制地图地体的显示范围超出区域自动弹回(实现思路)

    这篇文章主要介绍了arcgis.js控制地图地体的显示范围超出区域自动弹回,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借...

    码尚10372022-01-11
  • js教程基于JavaScript实现轮播图效果

    基于JavaScript实现轮播图效果

    这篇文章主要为大家详细介绍了基于JavaScript实现轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    努力学习中.....5592021-12-24
  • js教程js实现鼠标拖曳效果

    js实现鼠标拖曳效果

    这篇文章主要为大家详细介绍了js实现鼠标拖曳效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    等待的L先生8822021-12-22
  • js教程微信小程序onShareTimeline()实现分享朋友圈

    微信小程序onShareTimeline()实现分享朋友圈

    这篇文章主要给大家介绍了关于微信小程序onShareTimeline()实现分享朋友圈的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定...

    远航_6122021-12-27
  • js教程JavaScript实现原型封装轮播图

    JavaScript实现原型封装轮播图

    这篇文章主要为大家详细介绍了JavaScript原型封装轮播图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    zyhyoustrive12232021-12-21
  • js教程基于 Next.js 的 SSR/SSG 方案了解一下?

    基于 Next.js 的 SSR/SSG 方案了解一下?

    服务端渲染(SSR,Server Side Render)与客户端渲染(CSR,Client Side Render)的核心区分点简单来说就是完整的 HTML 文档在服务端还是浏览器里组装完成。...

    DYBOY4632021-12-27
  • js教程详解Typescript里的This的使用方法

    详解Typescript里的This的使用方法

    这篇文章主要介绍了详解Typescript里的This的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们...

    hardfist7252021-12-28