js原生的轮播,原理以及实践
轮播,无论是文字轮播还是图片轮播,他们的原理是一样的,都是通过定时器执行循环展示和影藏。
一、手动轮播
(1)原理
一系列的大小相等的图片平铺,利用CSS布局只显示一张图片,其余隐藏。通过计算偏移量利用定时器实现自动播放,或通过手动点击事件切换图片。
(2)实现
如何利用css实现布局显示一张图片?主要的属性是over-follow:hidden。首先给容器一个固定的长和宽,然后设置over-flow:hidden。
1、html结构
首先父容器container存放所有内容,子容器list存在图片。子容器buttons存放按钮小圆点。
<div id="container">
<div id="list" style="left: -600px;">
<img src="img/5.png" alt="1" />
<img src="img/1.png" alt="1" />
<img src="img/2.png" alt="2" />
<img src="img/3.png" alt="3" />
<img src="img/4.png" alt="4" />
<img src="img/5.png" alt="5" />
<img src="img/1.png" alt="5" />
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow"><</a>
<a href="javascript:;" id="next" class="arrow">></a>
</div>
优化,无缝滚动。
当你从最后一张图切换回第一张图时,有很大空白,利用两张辅助图来填补这个空白。
这里补充下无缝滚动,直接看代码,复制最后一张图片放置第一张图片前,同时复制第一张图片放置最后一张图片的后面。并且,将第一张图片辅助图(实际上是实际显示的第5张图片隐藏起来,故设置style="left: -600px;")
2、css样式
1、对盒子模型,文档流的理解,绝对定位问题。
2、注意list的overflow:hidden;只显示窗口的一张图片,把左右两边的都隐藏起来。
3、确保buttons中每个span所在层置顶,将其设置为最顶端。
* {
margin:;
padding:;
text-decoration: none;
} body {
padding: 20px;
} #container {
position: relative;
width: 600px;
height: 400px;
border: 3px solid #333;
overflow: hidden;
} #list {
position: absolute;
z-index:;
width: 4200px;
height: 400px;
} #list img {
float: left;
width: 600px;
height: 400px;
} #buttons {
position: absolute;
left: 250px;
bottom: 20px;
z-index:;
height: 10px;
width: 100px;
} #buttons span {
float: left;
margin-right: 5px;
width: 10px;
height: 10px;
border: 1px solid #fff;
border-radius: 50%;
background: #333;
cursor: pointer;
} #buttons .on {
background: orangered;
} .arrow {
position: absolute;
top: 180px;
z-index:;
display: none;
width: 40px;
height: 40px;
font-size: 36px;
font-weight: bold;
line-height: 35px;
text-align: center;
color: #fff;
background-color: RGBA(0, 0, 0, .3);
cursor: pointer;
} .arrow:hover {
background-color: RGBA(0, 0, 0, .7);
} #container:hover .arrow {
display: block;
} #prev {
left: 20px;
} #next {
right: 20px;
}
3、JS实现
首先我们先实现出手动点击左右两个箭头切换图片的效果:
window.onload = function() {
var list = document.getElementById('list');
var prev = document.getElementById('prev');
var next = document.getElementById('next'); function animate(offset) {
//获取的是style.left,是相对左边获取距离,所以第一张图后style.left都为负值,
//且style.left获取的是字符串,需要用parseInt()取整转化为数字。
var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft + 'px';
if(newLeft<-3000){
list.style.left = -600 + 'px';
}
if(newLeft>-600){
list.style.left = -3000 + 'px';
}
} prev.onclick = function() {
animate(600);
}
next.onclick = function() {
animate(-600);
}
}
效果如下图所示
运行后我们会发现,一直点击右箭头 ,会出现空白,而且,不能回到第一张图片。要点击左箭头才能回到第一张图片。
原因是我们利用偏移量left来获取图片,当看到left值小于3600时,因为没有第8张图片就出现空白,所以这里我们需要对偏移量做一个判断。
if(newLeft<-3000){
list.style.left = -600 + 'px';
}
if(newLeft>-600){
list.style.left = -3000 + 'px';
}
加了这个判断就是说,在实时的left值在小于-3000的时候,通过操作dom元素直接把left值给到-600,回到初始化的状态。
但是轮播有自动轮播和手动轮播。上面基本实现的是手动点击进行轮播(手动轮播)。
二、自动轮播
要实现自动,必须有定时器进行计时。
对于定时器,有必要说明一下setInterval()跟setTimeout的区别了。
简单来说,setInterval()执行多次,setTimeout()只执行一次。
所以自动轮播需要我们每隔一段时间执行一次,选择setInterval()函数。
/*自动循环播放*/
var timer;
function play(){
timer = setInterval(function(){
prev.onclick();
},1500)
}
play();
完美实现了自动轮播
但是,当我们想仔细看某一张图片时候,要把图片停住,我们清楚定时器就可以
三、手动可以干预轮播
我想仔细看某一张照片时候,要图片停住,需要用到window.clearInterval 这个方法。
这里,我们需要对其DOM操作,需要获取整个轮播图区域,鼠标进入到容器区域就清空计时器。
/*鼠标放上(离开)对应轮播暂停(播放)*/
var container = document.getElementById('container');
function stop() {
clearInterval(timer);
}
container.onmouseover = stop;
container.onmouseout = play;
效果,如下图所示:
一个鼠标放上轮播暂停的实现就完美实现了。
现在回顾一下,的确很简单,不是很难,并不是必须要用插件实现,原生的js也可以实现,你可以优化一下封装成自己的轮播插件。
(1)容器的css布局。
(2)每一次轮播通过偏移量left实现,手动轮播的按钮绑定每一次偏移量增加还是减少一张照片宽度的偏移量。
(3)自动轮播,通过setInterval()方法实现定时器,执行下一张的点击函数
(4)鼠标控制轮播的暂停和继续。通过onmouseover为暂停,onmouseout为继续。
完整代码:
<!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
text-decoration: none;
} body {
padding: 20px;
} #container {
position: relative;
width: 600px;
height: 400px;
border: 3px solid #333;
overflow: hidden;
} #list {
position: absolute;
z-index: 1;
width: 4200px;
height: 400px;
} #list img {
float: left;
width: 600px;
height: 400px;
} #buttons {
position: absolute;
left: 250px;
bottom: 20px;
z-index: 2;
height: 10px;
width: 100px;
} #buttons span {
float: left;
margin-right: 5px;
width: 10px;
height: 10px;
border: 1px solid #fff;
border-radius: 50%;
background: #333;
cursor: pointer;
} #buttons .on {
background: orangered;
} .arrow {
position: absolute;
top: 180px;
z-index: 2;
display: none;
width: 40px;
height: 40px;
font-size: 36px;
font-weight: bold;
line-height: 35px;
text-align: center;
color: #fff;
background-color: RGBA(0, 0, 0, .3);
cursor: pointer;
} .arrow:hover {
background-color: RGBA(0, 0, 0, .7);
} #container:hover .arrow {
display: block;
} #prev {
left: 20px;
} #next {
right: 20px;
}
</style>
</head> <body>
<div id="container">
<div id="list" style="left: -600px;">
<img src="img/5.png" alt="1" />
<img src="img/1.png" alt="1" />
<img src="img/2.png" alt="2" />
<img src="img/3.png" alt="3" />
<img src="img/4.png" alt="4" />
<img src="img/5.png" alt="5" />
<img src="img/1.png" alt="5" />
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow"><</a>
<a href="javascript:;" id="next" class="arrow">></a>
</div> </body> </html> <script>
window.onload = function() {
var list = document.getElementById('list');
var prev = document.getElementById('prev');
var next = document.getElementById('next'); function animate(offset) {
/*获取的是style.left,是相对左边获取距离,所以第一张图后style.left都为负值,
且style.left获取的是字符串,需要用parseInt()取整转化为数字。*/
var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft + 'px';
if(newLeft < -3000) {
list.style.left = -600 + 'px';
}
if(newLeft > -600) {
list.style.left = -3000 + 'px';
}
}
/*上一步*/
prev.onclick = function() {
animate(600);
}
/*下一步*/
next.onclick = function() {
animate(-600);
}
/*自动循环播放*/
var timer; function play() {
timer = setInterval(function() {
prev.onclick();
}, 1500)
}
play();
/*鼠标放上(离开)对应轮播暂停(播放)*/
var container = document.getElementById('container');
function stop() {
clearInterval(timer);
}
container.onmouseover = stop;
container.onmouseout = play;
}
</script>
四、小点也随着图片进行轮播
首先要能拿到有多少个小点的数组,然后每一次的下一步的时候判断一下当前的小圆点的标志位。
(1)当标志位大于数组的长度时候,需要把标志位赋值为初始值
/*上一步*/
prev.onclick = function() {
index = index -1;
if(index < 1) {
index = 5;
}
buttonShow();
animate(600);
}
/*下一步*/
next.onclick = function() {
index = index + 1;
if(index > 5) {
index = 1;
}
buttonShow();
animate(-600);
}
(2)每执行一次下一步,标志位temp+1,同时将圆点的上一个样式清除,下一个显示选中样式。
function buttonShow() {
/*console.log(buttons.length);*/
/*清除之前的样式*/
for(var i = 0; i < buttons.length; i++) {
if(buttons[i].className === 'on') {
buttons[i].className = '';
}
}
/*数组从0开始,temp从-1开始*/
buttons[index - 1].className = 'on';
}
最后效果如下图所示:
五、小点可以点击到对应的图片上
突然发现图片下边还有一堆小点,需要给增加点击事件,点击哪一个点,就到哪一张图片上。
/*小圆点的点击事件*/
for(var i =0;i<buttons.length;i++){
buttons[i].onclick = function (){
console.log(i);
/*偏移量的获取:获取鼠标的小圆点的位置,用this把index绑定到对象buttons[i]上*/
/*由于index是自定义属性,需要用到getAttribute()这个dom的2级方法,去获取自定义的index属性*/
var clickIndex = parseInt(this.getAttribute('index'));
var offset = 600*(index-clickIndex);
animate(offset);
index = clickIndex;
buttonShow();
}
}
要大功告成了,但是发现控制台会发现打印出来的永远的是i=5。
“对javascript来说,由for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中。”
就是说,js没有块级作用域这东西,(可能我C写多了,混淆了)。在第一次循环(从 i=0 到 4 这一过程)结束后,最后的 i 获取到的为 buttons.length 的值被
保存在for循环之外,最后鼠标点击任何一个小圆点时,自然访问的一直是 i=5 了。
使用立即函数
/*小圆点的点击事件*/
for(var i = 0; i < buttons.length; i++) {
/*使用立即函数*/
(function(i) {
buttons[i].onclick = function() {
console.log(i);
/*偏移量的获取:获取鼠标的小圆点的位置,用this把index绑定到对象buttons[i]上*/
/*由于index是自定义属性,需要用到getAttribute()这个dom的2级方法,去获取自定义的index属性*/
var clickIndex = parseInt(this.getAttribute('index'));
var offset = 600 * (index - clickIndex);
animate(offset);
index = clickIndex;
buttonShow();
}
})(i)
}
这里涉及到js的闭包问题。
完美原生js实现轮播,原理以及实践。总结一下:
原理:(1)使用的是css只显示一张图片,其余隐藏。通过计算偏移量利用定时器实现自动播放,或通过手动点击事件切换图片。
实践:http://www.mwcxs.top/%E8%BD%AE%E6%92%AD/index.html
更正(更正日期于2018.10.29)为:https://www.mwcxs.top/static/mybs/lunbo/index.html
欢迎访问:
1、云商城isv系统http://isv.suningcloud.com/mpisv-web/index
2、云商城消费者门户http://www.suningcloud.com/promotion/index/experience_center.html
追加于2018.10.29
完整的代码
<!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
text-decoration: none;
} body {
padding: 20px;
} #container {
position: relative;
width: 600px;
height: 400px;
border: 3px solid #333;
overflow: hidden;
} #list {
position: absolute;
z-index: 1;
width: 4200px;
height: 400px;
} #list img {
float: left;
width: 600px;
height: 400px;
} #buttons {
position: absolute;
left: 250px;
bottom: 20px;
z-index: 2;
height: 10px;
width: 100px;
} #buttons span {
float: left;
margin-right: 5px;
width: 10px;
height: 10px;
border: 1px solid #fff;
border-radius: 50%;
background: #333;
cursor: pointer;
} #buttons .on {
background: orangered;
} .arrow {
position: absolute;
top: 180px;
z-index: 2;
display: none;
width: 40px;
height: 40px;
font-size: 36px;
font-weight: bold;
line-height: 35px;
text-align: center;
color: #fff;
background-color: RGBA(0, 0, 0, .3);
cursor: pointer;
} .arrow:hover {
background-color: RGBA(0, 0, 0, .7);
} #container:hover .arrow {
display: block;
} #prev {
left: 20px;
} #next {
right: 20px;
}
</style>
</head> <body>
<div id="container">
<div id="list" style="left: -600px;">
<img src="img/5.png" alt="1" />
<img src="img/1.png" alt="1" />
<img src="img/2.png" alt="2" />
<img src="img/3.png" alt="3" />
<img src="img/4.png" alt="4" />
<img src="img/5.png" alt="5" />
<img src="img/1.png" alt="5" />
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow"><</a>
<a href="javascript:;" id="next" class="arrow">></a>
</div> </body> </html> <script>
window.onload = function() {
var list = document.getElementById('list');
var prev = document.getElementById('prev');
var next = document.getElementById('next'); function animate(offset) {
/*获取的是style.left,是相对左边获取距离,所以第一张图后style.left都为负值,
且style.left获取的是字符串,需要用parseInt()取整转化为数字。*/
var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft + 'px';
if(newLeft < -3000) {
list.style.left = -600 + 'px';
}
if(newLeft > -600) {
list.style.left = -3000 + 'px';
}
}
/*需要定位到按钮的样式*/
var buttons = document.getElementById('buttons').getElementsByTagName('span');
var index = 1; function buttonShow() {
/*console.log(buttons.length);*/
/*清除之前的样式*/
for(var i = 0; i < buttons.length; i++) {
if(buttons[i].className === 'on') {
buttons[i].className = '';
}
}
/*数组从0开始,temp从-1开始*/
buttons[index - 1].className = 'on';
}
/*上一步*/
prev.onclick = function() {
index = index - 1;
if(index < 1) {
index = 5;
}
buttonShow();
animate(600);
}
/*下一步*/
next.onclick = function() {
index = index + 1;
if(index > 5) {
index = 1;
}
buttonShow();
animate(-600);
}
/*自动循环播放*/
var timer; function play() {
timer = setInterval(function() {
next.onclick();
}, 1500)
}
play();
/*鼠标放上(离开)对应轮播暂停(播放)*/
var container = document.getElementById('container'); function stop() {
clearInterval(timer);
}
container.onmouseover = stop;
container.onmouseout = play; /*小圆点的点击事件*/
for(var i = 0; i < buttons.length; i++) {
/*使用立即函数*/
(function(i) {
buttons[i].onclick = function() {
console.log(i);
/*偏移量的获取:获取鼠标的小圆点的位置,用this把index绑定到对象buttons[i]上*/
/*由于index是自定义属性,需要用到getAttribute()这个dom的2级方法,去获取自定义的index属性*/
var clickIndex = parseInt(this.getAttribute('index'));
var offset = 600 * (index - clickIndex);
animate(offset);
index = clickIndex;
buttonShow();
}
})(i)
}
}
</script>
线上地址更换了,现在:https://www.mwcxs.top/static/mybs/lunbo/index.html
js原生的轮播,原理以及实践的更多相关文章
- js原生实现轮播图效果(面向对象编程)
面向对象编程js原生实现轮播图效果 1.先看效果图 2.需要实现的功能: 自动轮播 点击左右箭头按钮无缝轮播 点击数字按钮切换图片 分析:如何实现无缝轮播? 在一个固定大小的相框里有一个ul标签,其长 ...
- js原生实现轮播
前两天同事面试新人,让现场写”轮播的实现”.我一想这玩意貌似我也没写过啊,就在旁边暗搓搓地拖了一张纸也在那写,同事都纳闷了! 这玩意实现方法有很多种,就看喜欢那种,喜欢怎么写而已.我这里是通过对img ...
- js原生的轮播图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- JS+css3焦点轮播图PC端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 原生js实现图片轮播思路分析
一.复习原生js实现图片轮播 1.要点 自动轮播 点击小圆圈按钮,显示相应图片 点击左右箭头,实现向前向后轮播图片 2.实现思路 <div id="container"> ...
- 用jQuery基于原生js封装的轮播
我发现轮播在很多网站里面都用到过,一个绚丽的轮播可以为网页增色不少,最近闲来无事,也用原生js封装了一个轮播,可能不像网上的插件那么炫,但是也有用心去做.主要用了闭包的思想.需要传递的参数有:图片地址 ...
- jQuery与原生js实现banner轮播图
jQuery与原生js实现banner轮播图: (jq需自己加载)(图片需自己加载) <!DOCTYPE html> <html> <head> <meta ...
- 原生JS实现简易轮播图
原生JS实现简易轮播图(渐变?) 最近做网页总是会用到轮播图,我就把之前写的轮播图单独拿出来吧,如果有...如果真的有人也需要也可以复制去用用啊..哈~.. window.onload = funct ...
- 原生js实现无缝轮播
原生js实现无缝轮播 因为要做到无缝,所以就要把第一张图片和最后一张连接起来,在此处采用js克隆了第一张图片的节点,添加到最后,显示图片序号的小圆按钮也是使用js动态添加的. html部分 <d ...
随机推荐
- day2--第2章(计算机系统硬件核心知识)
第二章--计算机系统核心硬件知识 (一)互联网企业里PC服务器品牌及型号 互联网公司服务器品牌: DELL(大多数公司),HP,IBM(百度),浪潮,联想,航天联志. Dell服务器品牌: 1U = ...
- java三大框架项目和Redis组合使用
已知一个已有的Struts+Spring+Hibernate项目,以前使用MySQL数据库,现在想把Redis也整合进去.1. 相关Jar文件 下载并导入以下3个Jar文件: commons-pool ...
- 快速自检电脑是否被黑客入侵过(Windows版)
我们经常会感觉电脑行为有点奇怪, 比如总是打开莫名其妙的网站, 或者偶尔变卡(网络/CPU), 似乎自己"中毒"了, 但X60安全卫士或者X讯电脑管家扫描之后又说你电脑" ...
- bootstrap-wysihtml5设置值
今天做项目的时候用到了 bootstrap-wysihtml5,添加完一篇文章返回去继续添加的时候,js已经设置了将所有变量的值清空,但是不管用$('#someId').val(")还是$( ...
- Nodejs mongodb 管理组件adminmongodb
强大的 nodejs的mongodb管理工具,强大到即下即用: 安装需求: 1.git命令获取组件包,git clone https://github.com/mrvautin/adminMongo. ...
- 分布式网络文件系统--MooseFS
一.介绍 1.简介 MooseFS是一个具备冗余容错功能的分布式网络文件系统,它将数据分别存放在多个物理服务器或单独磁盘或分区上,确保一份数据有多个备份副本.对于访问的客户端或者用户来说,整个分布式网 ...
- .net core2.0下使用Identity改用dapper存储数据
前言. 已经好多天没写博客了,鉴于空闲无聊之时又兴起想写写博客,也当是给自己做个笔记.过了这么些天,我的文笔还是依然那么烂就请多多谅解了.今天主要是分享一下在使用.net core2.0下的实际遇到的 ...
- Could not resolve view with name '***' in servlet with name 'dispatcher'
今天在开发中遇到了一个问题,控制层使用的是SpringMVC框架. @RequestMapping("historyDetail") private String History( ...
- 在ThinkPHP中使用常量解决路由常规地址不安全传送数据问题
在ThinkPHP搭建项目的同时,会考虑到后期对静态页面的维护问题, 在项目的不断完善的同时,会有大量图片,css文件,以及js文件等一些容易修改.添加.或者删除的资源 如果在中后期对各个静态页面,j ...
- openstack pike 单机 一键安装 shell
#openstack pike 单机 centos 一键安装 shell #openstack pike 集群高可用 安装部署 汇总 http://www.cnblogs.com/elvi/p/7 ...