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. 强化学习基础篇【1】:基础知识点、马尔科夫决策过程、蒙特卡洛策略梯度定理、REINFORCE 算法

    强化学习基础篇[1]:基础知识点.马尔科夫决策过程.蒙特卡洛策略梯度定理.REINFORCE 算法 1.强化学习基础知识点 智能体(agent):智能体是强化学习算法的主体,它能够根据经验做出主观判断 ...

  2. Python自动化办公--Pandas玩转Excel数据分析【二】

    相关文章: Python自动化办公--Pandas玩转Excel[一] Python自动化办公--Pandas玩转Excel数据分析[三] python处理Excel实现自动化办公教学(含实战)[一] ...

  3. [zookeeper] 集群搭建及启动后查询服务器状态异常解决

    一.集群搭建 1.每台服务器上部署zookeeper 1.将zookeeper压缩包解压到指定位置,在zookeeper解压后目录下创建数据目录zkData 2.在zkData下创建myid文件,内容 ...

  4. Liunx知识点整理

    Linux知识点整理 目录和文件 ls (list)显示当前目录下的文件或目录 a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"."的视为隐藏档,不会列出) l 除文件 ...

  5. DNS正向解析

    实验介绍:正向解析 通常把域名到IP称为正向解析 把ip到域名称为反向解析 一:前期准备 准备一台客户端测试正向解析是否正常 修改ip 子网掩码 DNS服务器 使用VMnet8 IP要和DNS服务器端 ...

  6. RAPTOR:递归摘要与树形检索的结合,提升RAG检索性能

    RAPTOR:递归摘要与树形检索的结合,提升RAG检索性能 来源:ICLR'24 https://arxiv.org/pdf/2401.18059.pdf 随着 LLM 技术的发展,RAG 的价值也来 ...

  7. 【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I

    [LGR-148-Div.3]洛谷基础赛 #1 & MGOI Round I T1 luoguP9502 『MGOI』Simple Round I | A. 魔法数字 \(100pts\) 水 ...

  8. NC21125 践踏

    题目链接 题目 题目描述 首先给定一个定值k,支持如下操作(在数轴上) 加入一条线段[l,r] 删除一条已经存在的线段 给定x,问有多少个区间包含x+kt,其中t是一个整数变量,即t ∈ Z 比如说当 ...

  9. Laravel入坑指南(1)——Hello World

    接触PHP已经挺长一段时间了,一直对这个世界上最好的语言情有独钟.用熟练了之后,发现PHP不仅是天下第一,而且是宇宙第一.但是自从Laravel诞生之后,博主一直对Laravel有莫名的抵触,觉得这个 ...

  10. Idea 本人开发常用几款插件

    先说 idea装插件 首先,进入插件安装界面: 标注 1:显示 IntelliJ IDEA 的插件分类, All plugins:显示 IntelliJ IDEA 支持的所有插件: Enabled:显 ...