轮播图实现
demo
HTML部分#
-
slideshow
: 整个轮播图的框架 -
prev
: 上一页按钮 -
next
: 下一页按钮 -
promo
: 轮播图促销图片 -
circle
: 促销图片对应的按钮 -
promo_now
: 当前促销图片对应的按钮
<body>
<div class="slideshow">
<a src="" alt="" class="prev iconfont"><</a>
<a src="" alt="" class="next iconfont">></a>
<ul class="promo">
<li>
<img src="../../res/taobao-promo.png" alt="" class="promo_img" />
</li>
<li>
<img src="../../res/taobao-promo1.png" alt="" class="promo_img" />
</li>
<li>
<img src="../../res/taobao-promo2.png" alt="" class="promo_img" />
</li>
<li>
<img src="../../res/taobao-promo3.png" alt="" class="promo_img" />
</li>
</ul>
<ol class="circle">
</ol>
</div>
</body>
CSS部分#
- 注意: 后续需要添加动画的元素, 需要加上绝对定位.
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
.slideshow {
position: relative;
width: 600px;
height: 300px;
margin: 200px auto;
background-color: aliceblue;
border-radius: 10px;
overflow: hidden;
}
.prev,
.next {
display: none;
position: absolute;
top: 50%;
width: 20px;
height: 30px;
margin-top: -15px;
display: inline-block;
color: white;
background-color: rgba(0, 0, 0, .3);
text-align: center;
line-height: 30px;
z-index: 2;
}
.prev:hover,
.next:hover {
cursor: pointer;
}
.prev {
left: 0;
border-radius: 0 15px 15px 0;
}
.next {
right: 0;
border-radius: 15px 0 0 15px;
}
.promo {
position: absolute;
}
.promo li {
float: left;
}
.promo li .promo_img {
width: 600px;
height: 300px;
cursor: pointer;
}
.circle {
position: absolute;
right: 5%;
bottom: 5px;
height: 15px;
/* width: 50px; */
/* background-color: rgba(255, 255, 255, .7); */
border-radius: 10px;
}
.circle li {
float: left;
margin-top: 2px;
margin-left: 5px;
width: 10px;
height: 10px;
background-color: rgba(255, 255, 255, 1);
border-radius: 10px;
}
.circle li:hover {
background-color: coral;
cursor: pointer;
}
.circle .promo_now {
background-color: coral;
}
</style>
JS部分#
-
获取所需要操作的元素.
-
slideshow
: 轮播图整体框架. -
prev
: 轮播图上一页按钮. -
next
: 轮播图下一页按钮. -
promo
: 轮播图促销海报主体. -
circle
: 轮播图促销海报对应的按钮. -
imgWidth
: 轮播图一张促销海报的宽度.
-
-
鼠标经过轮播图显示上一页和下一页的图标, 鼠标离开轮播图隐藏上一页和下一页的图标.
- 给轮播图整体框架添加鼠标进入和离开事件.
-
动态设定轮播图促销海报主体的宽度.
-
由于后面为了优化第一张和最后一张的过渡动画, 所以我们这里动态调整的时候应该比
length
多一张. -
促销海报的总数 * 促销海报单张的宽度 = 轮播图促销海报主体的宽度
-
-
动态生成轮播图对应的显示按钮.
-
通过循环遍历, 动态生成按钮. 这样按钮数和促销海报数就可一一对应.
-
创建按钮的时候, 给每个按钮添加上点击事件, 让点击哪个按钮哪个按钮就以类名标记为当前按钮
promo_now
. 在添加前要使用排他思想, 清除所有按钮的promo_now
标记.
-
-
复制在轮播图中复制并尾插入轮播图的第一张图片,为了优化第一页和最后一页之间的切换动画.
-
克隆促销海报的第一张海报, 将其复制到所有海报的最后.
-
这样一来, 最后一张切换到第一张时, 我们可以先让其滚动到我们克隆的最后一张图片上. 等动画结束, 我们让轮播图迅速切换到第一张图片位置. 这样人眼无法发觉, 利用了一个小障眼法, 优化了动画效果.
-
第一张切换到最后一张同理, 先让其无动画迅速切换到最后一个克隆的轮播图位置. 之后再向前翻页, 切换到实际的最后一张海报. 优化动画效果.
-
-
实现轮播图下一页的逻辑.
-
获取当前按钮
promo_now
, 以及其编号index
, 以此来判断当前位于第几个轮播图. -
计算下一张轮播图所需要的移动坐标
target
. -
需要获取的信息完毕后, 清除当前轮播图的标记
promo_now
. -
使用封装好的动画函数移动轮播图, 当轮播图移动到最后一张时候, 让其施展障眼法瞬间移动到第一张.
-
给移动到的下一张轮播图添加当前轮播图标记
promo_now
.
-
-
实现轮播图上一页的逻辑.
-
获取当前按钮
promo_now
, 以及其编号index
, 以此来判断当前位于第几个轮播图. -
点击后判断, 当为第一张轮播图时, 施展障眼法瞬间移动到最后一张轮播图.
-
计算上一张轮播图所需要的移动坐标
target
. -
需要获取的信息完毕后, 清除当前轮播图的标记
promo_now
. -
使用封装好的动画函数移动轮播图.
-
给移动到的上一张轮播图添加当前轮播图标记
promo_now
.
-
-
播图点击按钮移动到相对应的轮播图。
-
获取当前点击按钮的
index
. -
计算移动到当前点击按钮位置轮播图所需要移动到的位置
target
. -
通过动画函数, 移动到计算好的位置.
-
-
实现轮播图定时自动切换下一页.
-
设置定时函数, 指定时间间隔调用以此, 下一页按钮.
-
当鼠标进入轮播图时, 定时器.
-
当鼠标离开时重新加载定时器.
-
<script>
// 1. 获取所需要操作的元素。
var slideshow = document.querySelector(".slideshow");
var prev = document.querySelector(".prev");
var next = document.querySelector(".next");
var ul = slideshow.querySelector(".promo");
var ol = slideshow.querySelector(".circle");
var imgWidth = slideshow.offsetWidth;
// 2. 鼠标经过轮播图显示上一页下一页
slideshow.addEventListener("mouseenter", function () {
prev.style.display = "block";
next.style.display = "block";
// 9. 实现轮播图定时自动切换下一页。
clearInterval(promo_auto);
})
// 2. 鼠标离开轮播图隐藏上一页下一页
slideshow.addEventListener("mouseleave", function () {
prev.style.display = "none";
next.style.display = "none";
// 9. 实现轮播图定时自动切换下一页。
promo_auto = setInterval(function () {
next.click();
}, 3000);
})
// 3. 动态设定轮播图本质主体的宽度。
ul.style.width = (ul.children.length + 1) * imgWidth + "px";
// 4. 动态生成轮播图对应的显示按钮。
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 = "promo_now";
// 8. 实现轮播图点击按钮移动到相对应的轮播图。
var promo_index = this.getAttribute("index");
target = promo_index * imgWidth;
animate(ul, -target);
})
}
// 设置第一个按钮为当前按钮
ol.children[0].className = "promo_now";
// 5. 复制在轮播图中复制并尾插入轮播图的第一张图片,为了优化第一页和最后一页之间的切换动画。
var ul0 = ul.children[0].cloneNode(true);
ul.appendChild(ul0);
// 6. 实现轮播图下一页的逻辑。
next.addEventListener("click", function () {
var promo_now = document.querySelector(".promo_now");
var promo_index = promo_now.getAttribute("index");
target = (promo_index - 0 + 1) * imgWidth;
promo_now.className = "";
animate(ul, -target, function () {
if ((promo_index - 0 + 1) == ol.children.length) {
ul.style.left = "0px";
}
});
if ((promo_index - 0 + 1) == ol.children.length) {
ol.children[0].className = "promo_now";
} else {
ol.children[promo_index - 0 + 1].className = "promo_now";
}
})
// 7. 实现轮播图上一页的逻辑。
prev.addEventListener("click", function () {
var promo_now = document.querySelector(".promo_now");
var promo_index = promo_now.getAttribute("index");
if (promo_index == 0) {
ul.style.left = -(ul.children.length - 1) * imgWidth + "px";
promo_index = (ul.children.length - 1);
}
target = (promo_index - 1) * imgWidth;
promo_now.className = "";
animate(ul, -target);
console.log("target:" + target);
console.log("promo_index:" + (promo_index - 1));
ol.children[promo_index - 1].className = "promo_now";
})
// 9. 实现轮播图定时自动切换下一页。
var promo_auto = setInterval(function () {
next.click();
}, 3000);
</script>
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 把步长值改为整数,来防止小数计算,使得目标到不了指定位置而无法停止
// 当step是正数向上取整(取大),当是负数向下取整(取小)
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();
}
obj.style.left = obj.offsetLeft + step + 'px';
// console.log('stop');
}, 10)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了