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. k8s 中的网络

    k8s 中的网络模型 CNI 网络插件 CNI 的设计思想 k8s 中的三层网络 Flannel 的 host-gw Calico 参考 k8s 中的网络模型 CNI 网络插件 docker 容器的网 ...

  2. 利用 ASP.NET Core 开发单机应用

    前言 现在是分布式微服务开发的时代,除了小工具和游戏之类刚需本地运行的程序已经很少见到纯单机应用.现在流行的Web应用由于物理隔离天然形成了分布式架构,核心业务由服务器运行,边缘业务由客户端运行.对于 ...

  3. Java - CodeForces - 469C

    题目: 现在有一个容器,里面有n个物品,编号为1-n,现在小q可以进行一些操作,每次取出任意两个数,可以把这两个数的编号相加,相减,相乘,再把结果放回容器.问最后小q能否在n-1次操作后使得容器里的唯 ...

  4. OLED 驱动模块程序代码

    1.前言 作为嵌入式软件开发,可能经常会使用单片机连接驱动显示屏,实现人机交互的功能,通常可选择的有 OLED 和 LCD 等,其中相关驱动代码例程网上更是数不胜数. 本文介绍的是 OLED, 常见代 ...

  5. Spring Boot 参数校验注解(自整理,不停的测试更新)

    首先我们只使用java官方的 javax.validation.constraints ,足以使用了,不使用spring boot 自身的,自身的与官方的一致,可能会有扩展,但是还得引入包,麻烦,只用 ...

  6. DbgridEh 导出 Excel 如果字段长度超过255会截断,那如何导出,另一种神奇的方法

    由于DbgridEh 导出 Excel 如果字段长度超过255会截断,所以必须换一种方法来导出,百度  谷歌 看了上百帖,都是有这句: xlApp := CreateOleObject('Excel. ...

  7. Hadoop组件兼容性

    (1)HBase和Hadoop.zookeeper.JDK兼容版本 参考网址: https://hbase.apache.org/book.html 1)JDK和Hbase的兼容版本  对于JDK,最 ...

  8. 【译】.NET 8 网络改进(一)

    原文 | Máňa,Natalia Kondratyeva 翻译 | 郑子铭 随着新的 .NET 版本的发布,发布有关网络空间中新的有趣变化的博客文章已成为一种传统.今年,我们希望引入 HTTP 空间 ...

  9. SQLServer复制表及数据的两种方法

    1.新表不存在(即复制数据的同时创建与旧表相同结构的新表):     select [col1,col2,col3...] into new_table from old_table where 1= ...

  10. NC16122 郊区春游

    题目链接 题目 题目描述 今天春天铁子的班上组织了一场春游,在铁子的城市里有n个郊区和m条无向道路,第i条道路连接郊区Ai和Bi,路费是Ci.经过铁子和顺溜的提议,他们决定去其中的R个郊区玩耍(不考虑 ...