共计 6986 个字符,预计需要花费 18 分钟才能阅读完成。
在一些我的项目开发中,咱们常常须要应用到轮播图,然而没有深刻学习的状况下做轮播图是十分艰难的。
思路
分成小问题来解决
1. 动静生成序号 12345
页面有多少li
(图片),就有多少序号
2. 点击序号、显示高亮、切换图片
2.1 给序号注册 onclick
事件
2.2 勾销其余序号高亮显示,让以后点击的序号高亮显示
2.3 点击序号,动画的形式切换到以后点击的图片地位(设置自定义属性,记录以后索引,有了索引就可用动画进行挪动)
3. 鼠标放到盒子上的时候显示左右箭头,移开时候暗藏
onmouseenter
和onmouseleave
4. 实现左右箭头播放上一张下一张(无缝滚动)
5. 隔多少工夫自动播放
setInterval
和 element.click()
联结即可实现
代码:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
list-style: none;
border: 0;
}
body {
margin: 0;
background-color: rgb(55, 190, 89);
}
.all {
width: 500px;
height: 200px;
padding: 4px;
margin: 100px auto;
position: relative;
background-color: #fff;
border-radius: 20px;
}
.screen {
width: 500px;
height: 200px;
border-radius: 17px;
overflow: hidden;
position: relative;
}
.screen li {
width: 500px;
height: 200px;
overflow: hidden;
float: left;
}
.screen ul {
position: absolute;
left: 0;
top: 0px;
width: 3000px;
}
.all ol {
position: absolute;
right: 180px;
bottom: 10px;
line-height: 20px;
text-align: center;
}
.all ol li {
float: left;
width: 20px;
height: 20px;
background: #fff;
border-radius: 10px;
border: 1px solid #ccc;
margin-left: 10px;
cursor: pointer;
opacity: 0.5;
/* 透明度 */
}
.all ol li.current {opacity: 1.0;}
#arr {
display: none;
z-index: 1000;
}
#arr span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑体';
font-size: 30px;
color: #fff;
opacity: 0.5;
border: 1px solid #fff;
border-radius: 5px;
}
#arr #right {
right: 5px;
left: auto;
}
</style>
</head>
<body>
<div class="all" id='box'>
<div class="screen">
<ul>
<li><img src="images/wf1.jpg" width="500" height="200" /></li>
<li><img src="images/wf2.jpg" width="500" height="200" /></li>
<li><img src="images/wf3.jpg" width="500" height="200" /></li>
<li><img src="images/wf4.jpg" width="500" height="200" /></li>
<li><img src="images/wf5.jpg" width="500" height="200" /></li>
</ul>
<ol>
</ol>
</div>
<div id="arr"><span id="left"><</span><span id="right">></span></div>
</div>
<script src="common.js"></script>
<script src="animate.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
// 获取元素
var box = my$('box');
var screen = box.children[0];
var ul = screen.children[0];
var ol = screen.children[1]
// 获取箭头
var arr = my$('arr');
var arrLeft = my$('left');
var arrRight = my$('right');
var count = ul.children.length; /* 获取图片数量 还没有放 cloneLi,所以数值是 5 */
var imgWidth = screen.offsetWidth; /* 获取的图片(盒子)的宽高 */
//1. 动静生成序号
for (i = 0; i < count; i++) {
// 在 ol 内创立 li
var li = document.createElement('li');
ol.appendChild(li);
// li 内赋予数值
setInnerText(li, i + 1);
li.onclick = liClick;
// 设置标签的自定义属性(创立索引)li.setAttribute('index', i);
}
// 2. 点击序号,切换,显示高亮
function liClick() {
// 勾销其余的 li 的高亮,显示以后 li 高亮
for (i = 0; i < ol.children.length; i++) {var li = ol.children[i];
li.className = '';
this.className = 'current';
}
// 获取的自定义属性是字符串类型,要转成整数
var liIndex = parseInt(this.getAttribute('index'));
animate(ul, -liIndex * imgWidth);
// 使得前面定义的全局变量 index 等于 li 的属性 liIndex
index = liIndex;
}
//ol 内的第一个 li 显示高亮色
ol.children[0].className = 'current';
//3. 鼠标放上去的时候显示箭头
// onmouseover 和 onmouseout 会触发事件冒泡;onmouseleave 和 onmouseenter 不会触发事件冒泡
box.onmouseenter = function () {
arr.style.display = 'block';
clearInterval(timeId);
}
box.onmouseleave = function () {
arr.style.display = 'none';
timeId = setInterval(function () {arrRight.click();
}, 2500)
}
// 4. 实现上一张,下一张的性能
var index = 0; // 第一张图片的索引
arrRight.onclick = function () {
// 判断是否是克隆的第一张图片,如果是克隆的第一张图片,此时批改 ul 的坐标,显示真正的第一张图片
if (index === count) {
ul.style.left = '0px';
index = 0;
}
// 如果是最初一张图片,不让 index++
index++;
// 有 5 张图片,然而还有一张克隆的图片,克隆图片索引是 5
if (index < count) {
// 获取图片对应的序号,让序号进行点击
ol.children[index].click();} else {animate(ul, -index * imgWidth);
// 勾销所有的高亮事实,让第一个序号高亮显示
for (var i = 0; i < ol.children.length; i++) {var li = ol.children[i];
li.className = '';
}
ol.children[0].className = 'current';
}
//
}
arrLeft.onclick = function () {if (index === 0) {
index = count;
ul.style.left = -index * imgWidth + 'px';
}
index--;
ol.children[index].click();}
// 无缝滚动
var firstLi = ul.children[0];
// 克隆 li
//cloneNode() 复制节点:参数 true 复制节点中的内容 ;false 只复制以后节点,不复制外面的内容
var cloneLi = firstLi.cloneNode(true);
ul.appendChild(cloneLi)
// 5. 自动播放
var timeId = setInterval(function () {
// 切换到下一张图片
arrRight.click();}, 2500)
common.js
function my$(id) {return document.getElementById(id);
}
// 解决浏览器兼容性
// 获取第一个子元素
function getFirstElementChild(element) {
var node, nodes = element.childNodes, i = 0;
while (node = nodes[i++]) {if (node.nodeType === 1) {return node;}
}
return null;
}
// 解决浏览器兼容性
// 获取下一个兄弟元素
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {if (el.nodeType === 1) {return el;}
}
return null;
}
// 解决 innerText 和 textContent 的兼容性问题
// 设置标签之间的内容
function setInnerText(element, content) {
// 判断以后浏览器是否反对 innerText
if (typeof element.innerText === 'string') {element.innerText = content;} else {element.textContent = content;}
}
// 解决注册事件的兼容性问题
// eventName, 不带 on,click mouseover mouseout
function addEventListener(element, eventName, fn) {
// 判断以后浏览器是否反对 addEventListener 办法
if (element.addEventListener) {element.addEventListener(eventName, fn); // 第三个参数 默认是 false
} else if (element.attachEvent) {element.attachEvent('on' + eventName, fn);
} else {
// 相当于 element.onclick = fn;
element['on' + eventName] = fn;
}
}
// 解决移除事件的兼容性解决
function removeEventListener(element, eventName, fn) {if (element.removeEventListener) {element.removeEventListener(eventName, fn);
} else if (element.detachEvent) {element.detachEvent('on' + eventName, fn);
} else {element['on' + eventName] = null;
}
}
// 获取页面滚动间隔的浏览器兼容性问题
// 获取页面滚动进来的间隔
function getScroll() {
var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
return {
scrollLeft: scrollLeft,
scrollTop: scrollTop
}
}
// 获取鼠标在页面的地位,解决浏览器兼容性
function getPage(e) {var pageX = e.pageX || e.clientX + getScroll().scrollLeft;
var pageY = e.pageY || e.clientY + getScroll().scrollTop;
return {
pageX: pageX,
pageY: pageY
}
}
// 格式化日期对象,返回 yyyy-MM-dd HH:mm:ss 的模式
function formatDate(date) {
// 判断参数 date 是否是日期对象
// instanceof instance 实例(对象) of 的
// console.log(date instanceof Date);
if (!(date instanceof Date)) {console.error('date 不是日期对象')
return;
}
var year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate(),
hour = date.getHours(),
minute = date.getMinutes(),
second = date.getSeconds();
month = month < 10 ? '0' + month : month;
day = day < 10 ? '0' + day : day;
hour = hour < 10 ? '0' + hour : hour;
minute = minute < 10 ? '0' + minute : minute;
second = second < 10 ? '0' + second : second;
return year + '-' + month + '-' + day + '' + hour +':'+ minute +':' + second;
}
// 获取两个日期的时间差
function getInterval(start, end) {
// 两个日期对象,相差的毫秒数
var interval = end - start;
// 求 相差的天数 / 小时数 / 分钟数 / 秒数
var day, hour, minute, second;
// 两个日期对象,相差的秒数
// interval = interval / 1000;
interval /= 1000;
day = Math.round(interval / 60 / 60 / 24);
hour = Math.round(interval / 60 / 60 % 24);
minute = Math.round(interval / 60 % 60);
second = Math.round(interval % 60);
return {
day: day,
hour: hour,
minute: minute,
second: second
}
}
animate.js
// var timerId = null;
// 封装动画的函数
function animate(element, target) {
// 通过判断,保障页面上只有一个定时器在执行动画
if (element.timerId) {clearInterval(element.timerId);
element.timerId = null;
}
element.timerId = setInterval(function () {
// 步进 每次挪动的间隔
var step = 10;
// 盒子以后的地位
var current = element.offsetLeft;
// 当从 400 到 800 执行动画
// 当从 800 到 400 不执行动画
// 判断如果以后地位 > 指标地位 此时的 step 要小于 0
if (current > target) {step = - Math.abs(step);
}
// Math.abs(current - target) <= Math.abs(step)
if (Math.abs(current - target) <= Math.abs(step)) {
// 让定时器进行
clearInterval(element.timerId);
// 让盒子到 target 的地位
element.style.left = target + 'px';
return;
}
// 挪动盒子
current += step;
element.style.left = current + 'px';
}, 5);
}
正文完
发表至: javascript
2020-08-19