JS实现轮播图2
今天我们继续来介绍一下 轮播图 下面的indicator 区域的实现。 上一篇文章轮播图 我们重点介绍了实现原理,以及html 结构,这里基于之前的结构 编写 indicator 区域的实现。
思路分析
移动图片
红色框框的区域的实现,首先布局 给一个 绝对定位, 指定 bottom ,left,right 这些值 把这个区域定位到对应到右下角。
如何实现 点 小点 来移动 图片呢?
我们可以给每个 小点一个value 的属性,值为第几张图片的索引信息。
然后在父元素 绑定 点击事件, 通过事件冒泡的方式, 获取我们当前点击了哪个小点,然后获取value 值, 根据value 值计算 对应要偏离的距离
<div class="banner-dots">
<span class="active" value="0"></span>
<span class="" value="1"></span>
<span class="" value="2"></span>
<span class="" value="3"></span>
</div>
首先实现一个moveTo(index) ,此时 index 从零开始的, 根据index 来移动 carousel
的 transform 属性 translateX 的值,
比如
index=1 , 那说明要移动一个图片宽度的距离
index=2 , 那说明要移动两个个图片宽度的距离
依次类推。。。
// // 根据 index 移动carousel 位置
function moveTo(index) {
let currentX = (parseInt(index)) * imgWidth * -1;
// console.log('currentX:', currentX);
carousel.style.transform = `translateX(${currentX}px)`;
}
绑定事件
我们在父元素 绑定 click 事件
bannerDots.addEventListener('click', function(e) {})
当鼠标点击 子元素的时候,事件会冒泡传递到父元素的click
的事件上,父元素如何知道 点击了哪个元素呢?
我们可以通过 funciton(e){}
来获取这个event, 通过 e.target
就可以获取对应的 元素了, 然后获取元素对应的索引,然后可以使用 moveTo(index)
来进行移动 图片。 同时 我们还要控制 当前激活的图片,即当前要展示的图片。 我们需要给当前的图片 添加一个样式,或者类 来区分。 然后还要把之前的状态置为 未激活的状态。
激活对应的状态
我的做法就是把所有的点都找到 然后去掉 active
class , 然后在当前的图片上重新添加 active
class 这样 就完成了,小点跟随的变化。
对应active 宽度 稍微大一点,来区分。
.container .banner-dots span.active {
width: 20px;
}
同理 left,right 的移动, 也要对小点的区域进行联动,这个时候 我们只需要 计算出当前是第几张图片,首先 重置所有小点的状态, 然后进行激活当前的图片。
完整实现
html 页面以及 css 布局如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>流浪法师</title>
<script src="./slides.js" defer></script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
h1 {
text-align: center;
margin: 25px auto;
}
.container {
position: relative;
margin: 30px auto;
width: 782px;
height: 573px;
overflow: hidden;
background-color: #f5f5f5;
}
.carousel {
display: flex;
flex-wrap: nowrap;
transition: all 0.2s;
}
.carousel>.item {
width: 782px;
height: 573px;
flex: 0 0 782px;
}
.carousel>.item>img {
height: 100%;
width: 100%;
object-fit: cover;
object-position: center top;
}
.container .left,
.container .right {
width: 70px;
height: 70px;
position: absolute;
top: 50%;
transform: translateY(-50%);
text-align: center;
color: #f1f1f1;
line-height: 55px;
font-size: 55px;
vertical-align: bottom;
background: rgba(28, 31, 33, .1);
border-radius: 50%;
}
.container .left {
left: 0;
}
.container .right {
right: 0;
}
.container .left:hover,
.container .right:hover {
background: rgba(28, 31, 33, .5);
border-radius: 50%;
cursor: pointer;
font-weight: 500;
color: #fff;
}
.container .banner-dots {
position: absolute;
bottom: 20px;
left: 0;
right: 0;
text-align: right;
padding-right: 24px;
line-height: 12px;
}
.container .banner-dots span {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 4px;
margin-left: 8px;
background: rgba(255, 255, 255, .75);
transition: all .2s;
cursor: pointer;
}
.container .banner-dots span:hover {
cursor: pointer;
width: 20px;
}
.container .banner-dots span.active {
width: 20px;
}
</style>
</head>
<body>
<div class="wrapper">
<h1>流浪法师</h1>
<div class="container">
<div class="carousel">
<div class="item"><img src="./img/守护者雕像 瑞兹1.jpeg" alt=""></div>
<div class="item"><img src="./img/美国大叔 瑞兹2.jpeg" alt=""></div>
<div class="item"><img src="./img/部落精神 瑞兹3.jpeg" alt=""></div>
<div class="item"><img src="./img/符文法师4.jpeg" alt=""></div>
</div>
<div class="left" onclick=""><</div>
<div class="right" onclick="">></div>
<div class="banner-dots">
<span class="active" value="0"></span>
<span class="" value="1"></span>
<span class="" value="2"></span>
<span class="" value="3"></span>
</div>
</div>
</div>
</body>
</html>
JavaScript 如下
slide.js
// 获取dom 结点
let left = document.querySelector('.left');
let right = document.querySelector('.right');
let carousel = document.querySelector('.carousel');
let bannerDots = document.querySelector('.banner-dots');
let allSpans = document.querySelectorAll('.banner-dots > span');
// 图片总的数量
const imgCount = 4;
// 一张图片基本宽度
const imgWidth = 782;
// 默认第一张图片偏移 的位置
let currentX = 0;
// 边界位置
const maxTranslateX = imgWidth * (imgCount - 1);
// 确定当前的位置是 第几张 图片
function assureIndex(currentX) {
currentX = Math.abs(currentX)
index = currentX / imgWidth
// console.log('index:', index);
return index;
}
// 根据 index 寻找 第几张图片
function lookTarget(index) {
// body > div > div > div.banner-dots > span:nth-child(1)
position = index + 1;
const target = span = document.querySelector(`.banner-dots > span:nth-child(${position})`)
// console.log('span:', span, 'index:', index);
return target;
}
// 移除所有的allSpans acitve 的类
function removeAllActive() {
for (let i = 0; i < allSpans.length; i++) {
span = allSpans[i];
span.classList.remove('active');
}
}
// 激活 indicator 区域
function acitveTarget(currentX) {
const index = assureIndex((currentX));
const target = lookTarget(index);
removeAllActive();
target.classList.add('active');
}
left.addEventListener('click', function() {
// console.log('click left');
if (currentX === 0) {
// 显示最后一张图片
currentX += imgWidth * (imgCount - 1) * -1;
} else if (Math.abs(currentX) <= maxTranslateX) {
// 没有超出范围 正常移动即可
currentX += imgWidth;
} else {
currentX = 0;
}
// setting translateX 偏移方向
carousel.style.transform = `translateX(${currentX}px)`;
acitveTarget(currentX);
})
right.addEventListener('click', function() {
// console.log('click right');
// 没有超出范围就正常移动,currentX - imgWidth
if (Math.abs(currentX) < maxTranslateX) {
currentX -= imgWidth;
} else {
// 显示第一张 幻灯片
currentX = 0;
}
// setting translateX 偏移方向
carousel.style.transform = `translateX(${currentX}px)`;
acitveTarget(currentX);
})
// 根据 index 移动carousel 位置
function moveTo(index) {
let currentX = (parseInt(index)) * imgWidth * -1;
// console.log('currentX:', currentX);
carousel.style.transform = `translateX(${currentX}px)`;
}
bannerDots.addEventListener('click', function(e) {
// console.log(e.target);
// 获取点击了那个 span 标签
const target = e.target;
const index = target.getAttribute('value');
// console.log('index:', index);
moveTo(index);
// 移除所有的 active
removeAllActive();
// 添加当前的active
target.classList.add('active');
})
/*
https://developer.mozilla.org/zh-TW/docs/Web/API/Element/classList
https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
*/
总结
本文为 轮播图第二弹,完成了indicator 区域的联动效果,感兴趣的同学 可以尝试自己来写一下看看哦。