1. 鼠标经过轮播图模块,左右按钮提示,离开隐藏左右按钮
  2. 点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理
  3. 图片播放的同时,下面小圆圈模块跟随一起变化
  4. 点击小圆圈,可以播放相应图片
  5. 鼠标不经过轮播图,轮播图也会自动播放图片
  6. 鼠标经过,轮播图模块自动播放停止

第一步 鼠标经过显示按钮 鼠标离开按钮消失

    //获取元素
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var focus = document.querySelector('.focus');
//鼠标经过显示按钮
focus.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
})
focus.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
})

第二步:考虑如何动态生成小圆圈 让小圆圈个数与图片个数一致

首先得到ul里图片个数,利用循环动态生成小圆圈,创建节点并插入节点,然后给第一个小圆圈插入current类

    //动态生成小圆圈
var ul = focus.querySelector('ul');//必须限定focus里面的
var ol = focus.querySelector('.circle');
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement('li');
ol.appendChild(li);
//[]
}
ol.children[0].className = 'current';//第一个小圆圈默认变色

第三步:利用排他思想,实现点击小圆圈变色

        //可以直接在生成小圆圈的同时绑定点击事件
li.addEventListener('click', function () {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
this.className = 'current';
})

第四步:点击小圆圈滚动图片

注意是ul在移动

当点击某个小圆圈,就让图片滚动,移动距离为图片索引号*图片宽度

知识点:索引号如何得到?

  • 通过给每个li设定自定义属性点击时获取自定义属性
    var ul = focus.querySelector('ul');//必须限定focus里面的
var ol = focus.querySelector('.circle');
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement('li');
//通过自定义属性记录小圆圈索引号
li.setAttribute('index', i);
ol.appendChild(li);
//可以直接在生成小圆圈的同时绑定点击事件
li.addEventListener('click', function () {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
this.className = 'current';
//点击小圆圈移动图片
var index = this.getAttribute('index');
var focusWidth = focus.offsetWidth;
animate(ul, -index * focusWidth);
})
}

第五步:点击左右按钮滚动

思路:声明一个变量,每点击一次number++

但是当点击次数过多会走到空白区域

如何实现无缝滚动?

  • 把ul第一个li复制一份,放到ul后面,当图片滚动到克隆的最后一张的时候不做动画直接快速跳回第一张:left=0,同时num=0;

如何克隆第一张图片?

  • 利用节点的克隆和添加操作
    ol.children[0].className = 'current';//第一个小圆圈默认变色
var firstLi = ul.children[0].cloneNode(true);
ul.appendChild(firstLi);//克隆第一张图
var num = 0;
arrow_r.addEventListener('click', function () {
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth);
})

第六步:点击按钮小圆圈跟随变化

再定义一个变量circle,每次点击一次按钮则++,如果circle==4,说明走到最后这张图片,使circle复原

    var circle = 0;
arrow_r.addEventListener('click', function () {
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth);
//实现点击按钮小圆圈跟随变化
circle++; if (circle == ol.children.length) {
circle = 0;
}
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';

第七步:此时有两个bug

按钮的点击操作和圆点的点击是不同变量,无法共同使用,两个事件的变量需要同步

应该在点击小圆点事件中添加

num = index;
circle = index;

第八步:左侧按钮同理

arrow_l.addEventListener('click', function () {
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * focusWidth + 'px';
}
num--;
animate(ul, -num * focusWidth);
//实现点击按钮小圆圈跟随变化
circle--; if (circle < 0) {
circle = ol.children.length - 1;
}
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';
})

第十步 代码优化 相同的可以封装函数

    function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';
}

三元表达式简化

        circle = circle < 0 ? ol.children.length - 1 : circle;
// if (circle < 0) {
// circle = ol.children.length - 1;
// }

最后:自动播放!

发现自动播放时和点击右侧按钮很类似

可以手动调用右侧按钮点击事件arrow_r.click()

    focus.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);//鼠标经过停止定时器
timer = none;
})
focus.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function () {//鼠标离开开启定时器
arrow_r.click();//手动调用点击事件
}, 2000)
})

补充:节流阀

防止轮播图按钮连续点击造成播放过快

目的:当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触发

利用回调函数,添加一个变量来控制,锁住函数和解锁函数

  • 开始设置一个变量var flag=true
  • if(flag) {flag=false;do something}关闭水龙头

利用回调函数 动画执行完毕(使用回调函数),false=true 打开水龙头

完整js代码

window.addEventListener('load', function () {
//获取元素
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var focus = document.querySelector('.focus');
var focusWidth = focus.offsetWidth;
var num = 0;
//鼠标经过显示按钮
focus.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);//鼠标经过停止定时器
timer = none;
})
focus.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function () {//鼠标离开开启定时器
arrow_r.click();//手动调用点击事件
}, 2000)
}) //动态生成小圆圈
var ul = focus.querySelector('ul');//必须限定focus里面的
var ol = focus.querySelector('.circle');
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement('li');
//通过自定义属性记录小圆圈索引号
li.setAttribute('index', i);
ol.appendChild(li);
//可以直接在生成小圆圈的同时绑定点击事件
li.addEventListener('click', function () {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
this.className = 'current';
//点击小圆圈移动图片
var index = this.getAttribute('index');
//当我们点击了某个li,就要把这个li的索引号给num//////////////////////////////bug必须改
num = index;
circle = index;
animate(ul, -index * focusWidth);
})
}
ol.children[0].className = 'current';//第一个小圆圈默认变色
var firstLi = ul.children[0].cloneNode(true);
ul.appendChild(firstLi);//克隆第一张图 var circle = 0;//全局变量
var flag = true;
arrow_r.addEventListener('click', function () {
if (flag) {
flag = false;//关闭节流阀
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth, function () {
flag = true;//打开节流阀
});
//实现点击按钮小圆圈跟随变化
circle++; if (circle == ol.children.length) {
circle = 0;
}
circleChange();
} }) arrow_l.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * focusWidth + 'px'; }
num--;
animate(ul, -num * focusWidth, function () {
flag = true;
});
//实现点击按钮小圆圈跟随变化
circle--;
circle = circle < 0 ? ol.children.length - 1 : circle;
// if (circle < 0) {
// circle = ol.children.length - 1;
// }
circleChange();
}
})
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';
}
var timer = setInterval(function () {
arrow_r.click();//手动调用点击事件
}, 2000)
})

animate.js

function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback() // 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();//借助短路运算如果有参数传入才会调用callback
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px'; }, 15);
}

相关html

<div class="focus">
<a href="javascript:;" class="arrow-l">&lt;</a>
<a href="javascript:;" class="arrow-r">&gt;</a>
<ul>
<li><a href="#"><img src="upload/focus1.png" alt=""></a></li>
<li><a href="#"><img src="upload/focus1.jpg" alt=""></a></li>
<li><a href="#"><img src="upload/focus2.jpg" alt=""></a></li>
<li><a href="#"><img src="upload/focus3.jpg" alt=""></a></li> </ul>
<ol class="circle"> </ol>

相关css

.focus {
float: left;
overflow: hidden;
position: relative;
width: 721px;
height: 455px; } .arrow-l,.arrow-r {
display: none;
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
color:rgb(175, 170, 170);
font-size: 20px;
line-height: 40px;
text-align: center;
z-index: 10;
background:rgba(0,0,0, .5); }
.arrow-l {
left: 0;
border-radius: 0 30px 30px 0; }
.arrow-r {
right: 0;
border-radius: 30px 0 0 30px; }
.focus ul{
position: absolute;
top: 0;
left: 0;
width: 600%;
}
.focus ul li{
float: left;
}
.circle{
position: absolute;
bottom: 0;
left: 40px;
bottom: 0;
height: 18px;
width: 150px; }
.circle li{
height: 12px;
width: 12px;
float: left;
border-radius: 8px;
border: 1px solid #e4e4e4;
margin: 0 4px;
}
.current {
background-color: #e4e4e4;
}

JS案例-网页轮播图的更多相关文章

  1. 原生JS实现简易轮播图

    原生JS实现简易轮播图(渐变?) 最近做网页总是会用到轮播图,我就把之前写的轮播图单独拿出来吧,如果有...如果真的有人也需要也可以复制去用用啊..哈~.. window.onload = funct ...

  2. jQuery与原生js实现banner轮播图

    jQuery与原生js实现banner轮播图: (jq需自己加载)(图片需自己加载) <!DOCTYPE html> <html> <head> <meta ...

  3. JS+css3焦点轮播图PC端

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. js原生实现轮播图效果(面向对象编程)

    面向对象编程js原生实现轮播图效果 1.先看效果图 2.需要实现的功能: 自动轮播 点击左右箭头按钮无缝轮播 点击数字按钮切换图片 分析:如何实现无缝轮播? 在一个固定大小的相框里有一个ul标签,其长 ...

  5. js - 面向对象 - 小案例:轮播图、随机点名、选项卡、鼠标拖拽

    面向对象 对象 : (黑盒子)不了解内部结构, 知道表面的各种操作. 面向对象 : 不了解原理的情况下 会使用功能 . 面向对象是一种通用思想,并非编程中能用,任何事情都能用. 编程语言的面向对象的特 ...

  6. JS学习笔记--轮播图效果

    希望通过自己的学习收获哪怕收获一点点,进步一点点都是值得的,加油吧!!! 本章知识点:index this for if else 下边我分享下通过老师教的方式写的轮播图,基础知识实现: 1.css代 ...

  7. 原生 js 左右切换轮播图

    使用方法: 可能很多人对轮播图感兴趣,下面奉上本人的 原生 js 轮播代码复制 js 到页面的最底部,样式在 css 里改,js 基本不用动,有什么不懂的可以 加本人 QQ172360937 咨询 或 ...

  8. photoSlider-原生js移动开发轮播图、相册滑动插件

    详细内容请点击 在线预览   立即下载 使用方法: 分别引用css文件和js文件 如: <link rel="stylesheet" type="text/css& ...

  9. photoSlider-html5原生js移动开发轮播图-相册滑动插件

    简单的移动端图片滑动切换浏览插件 分别引用css文件和js文件 如: <link rel="stylesheet" type="text/css" hre ...

  10. 用 JS 写 (轮播图 / 选项卡 / 滑动门)

    页面中经常会用到各式各样的轮播图,今天贺贺为大家介绍一种常用的方法,对于JS我们需要举一反三,一种方法可以对多个轮播样式进行渲染. <head> <meta charset=&quo ...

随机推荐

  1. Java 自增自减运算符和移位运算符介绍

    摘自 JavaGuide (「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识.准备 Java 面试,首选 JavaGuide!) 自增自减运算符 在写代码的过程中,常见的 ...

  2. SqlSugar的Repository

    1.仓储说明 仓储可以让你的方法更加的规范,需要什么方法都封装到仓储中,下次就能重复使用,并且能很好的和你业务拆分开 这种设计模式简单粗暴用起来也方便 ,文章下面有可以运行的DEMO 2.仓储方法 仓 ...

  3. 环境调试bug【一】

    1.报错修改`np.bool`---bool H:\Anaconda3-2020.02\envs\parl\lib\site-packages\paddle\fluid\framework.py:54 ...

  4. C++ LibCurl实现Web隐藏目录扫描

    LibCurl是一个开源的免费的多协议数据传输开源库,该框架具备跨平台性,开源免费,并提供了包括HTTP.FTP.SMTP.POP3等协议的功能,使用libcurl可以方便地进行网络数据传输操作,如发 ...

  5. Python 使用sigthief签发证书

    Windows 系统中的一些非常重要文件通常会被添加数字签名,其目的是用来防止被篡改,能确保用户通过互联网下载时能确信此代码没有被非法篡改和来源可信,从而保护了代码的完整性.保护了用户不会被病毒.恶意 ...

  6. RPA AI .NET Core 与未来--学习笔记

    摘要 当下 RPA 平台主要采用 .NET Framework 框架,也限制了 RPA 只用于 Windows 平台..NET Core 的开放与跨平台特性赋予 RPA 更大发展空间. RPA是什么 ...

  7. HBase-Hbase启动异常java.lang.IllegalArgumentException: object is not an instance of declaring class

    1.问题描述 HBase启动时异常如下: java.lang.IllegalArgumentException: object is not an instance of declaring clas ...

  8. PCG——程序化地形生成(1)

    前言 接触了半年多Houdini,佛系研究了一下PCG(Procedural Content Generation)相关的技术,这真是个好东西,赶在年前写个总结.Houdini 一款DCC软件,功能又 ...

  9. ABC 305

    题目列表 前三题过水,第四题分类讨论两个端点之间的距离和所在位置是清醒或睡眠 即可. E 题意:一张图上有一些结点有保安,每个保安有不同的警戒度 \(h_i\),定义 一个结点是安全的 为这个结点可以 ...

  10. NC19325 游戏

    题目链接 题目 题目描述 BLUESKY007,fengxunling和dreagonm三个人发现了一个像素游戏,这款神奇的游戏每次会生成一个nxm的网格,其中每一个格子都被随机染色为R,G,B三种颜 ...