原生JS实现轮播图
前言
轮播图是一个常见的组件,今天我们使用原生JavaScript来实现。
先来看看效果图:
实现
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图</title>
<link rel="stylesheet" href="./css/index.css" />"
</head>
<body>
<div class="container">
<div class="carousel">
<div class="item"><a href=""><img src="./img/1.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/2.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/3.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/4.jpg" alt=""></a></div>
</div>
<div class="indicator">
<span class="active"></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<script src="./js/index.js"></script>
</body>
</html>
css/index.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 500px;
height: 300px;
margin: 10px auto;
overflow: hidden;
position: relative;
}
.carousel {
width: 100%;
height: 100%;
display: flex;
transition: all .5s;
}
.carousel img {
width: 500px;
height: 300px;
}
.indicator {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.indicator span {
width: 12px;
height: 12px;
border: 2px solid #ccc;
border-radius: 50%;
margin: 0 3px;
}
.indicator span.active {
background: #fff;
border-color: #fff;
}
js/index.js
const query = (el) => {
return document.querySelector(el)
}
const queryAll = (el) => {
return document.querySelectorAll(el)
}
const doms = {
carousel: query('.carousel'),
indicators: queryAll('.indicator span')
}
let curIndex = 0
function moveTo(index) {
doms.carousel.style.transform = `translateX(-${index * 100}%)`
const active = query('.indicator .active')
active.classList.remove('active')
doms.indicators[index].classList.add('active')
curIndex = index
}
function initEvents() {
doms.indicators.forEach((item, index) => {
item.onclick = () => {
moveTo(index)
}
})
}
initEvents()
这样,就实现了一个简单的轮播图
完善
接下来,我们来完善这个轮播图的功能,加上左右切换并实现无缝切换。
- index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图</title>
<link rel="stylesheet" href="./css/index.css" />"
</head>
<body>
<div class="container">
<div class="carousel">
<div class="item"><a href=""><img src="./img/1.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/2.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/3.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./img/4.jpg" alt=""></a></div>
</div>
<div class="arrow arrow-left"><</div>
<div class="arrow arrow-right">></div>
<div class="indicator">
<span class="active"></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<script src="./js/index.js"></script>
</body>
</html>
- css/index.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 500px;
height: 300px;
margin: 10px auto;
overflow: hidden;
position: relative;
}
.carousel {
width: 100%;
height: 100%;
display: flex;
transition: all .5s;
}
.carousel img {
width: 500px;
height: 300px;
}
.indicator {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.indicator span {
width: 12px;
height: 12px;
border: 2px solid #ccc;
border-radius: 50%;
margin: 0 3px;
}
.indicator span.active {
background: #fff;
border-color: #fff;
}
.arrow {
position: absolute;
width: 40px;
height: 40px;
background-color: red;
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
background: rgba(0, 0, 0, 0.2);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.arrow-left {
left: 10px;
}
.arrow-right {
right: 10px;
}
- js/index.js
const query = (el) => {
return document.querySelector(el)
}
const queryAll = (el) => {
return document.querySelectorAll(el)
}
const doms = {
carousel: query('.carousel'),
indicators: queryAll('.indicator span'),
leftArrow: query('.arrow-left'),
rightArrow: query('.arrow-right'),
}
const count = doms.indicators.length
let curIndex = 0
function moveTo(index) {
doms.carousel.style.transform = `translateX(-${index * 100}%)`
const active = query('.indicator .active')
active.classList.remove('active')
doms.indicators[index].classList.add('active')
curIndex = index
}
function toLeft() {
if (curIndex === 0) {
console.log('无缝切换')
} else {
moveTo(curIndex - 1)
}
}
function toRight() {
if (curIndex === count - 1) {
console.log('无缝切换')
} else {
moveTo(curIndex + 1)
}
}
function initEvents() {
doms.indicators.forEach((item, index) => {
item.onclick = () => {
moveTo(index)
}
})
doms.leftArrow.onclick = () => toLeft()
doms.rightArrow.onclick = () => toRight()
}
initEvents()
接下来,实现无缝切换。
将第一张图放到末尾,将最后一张图放到开头
- 第一种情况:当轮播图到最后一张图,需要右切换时: 我们直接把当前位置切换为开头的图,然后再切换到第(0)张图
- 第二种情况:当轮播图到第一张图,需要左切换时: 我们直接把当前位置切换为开头的图,然后再切换到第(0)张图
js/index.js
const query = (el) => {
return document.querySelector(el)
}
const queryAll = (el) => {
return document.querySelectorAll(el)
}
const doms = {
carousel: query('.carousel'),
indicators: queryAll('.indicator span'),
leftArrow: query('.arrow-left'),
rightArrow: query('.arrow-right'),
}
const count = doms.indicators.length
let curIndex = 0
function moveTo(index) {
doms.carousel.style.transform = `translateX(-${index * 100}%)`
doms.carousel.style.transition = 'all .5s'
const active = query('.indicator .active')
active.classList.remove('active')
doms.indicators[index].classList.add('active')
curIndex = index
}
function toLeft() {
if (curIndex === 0) {
doms.carousel.style.transform = `translateX(-${count * 100}%)`
doms.carousel.style.transition = 'none'
// 这里添加强制渲染是为了有过渡效果
doms.carousel.clientWidth // 强制渲染
moveTo(count - 1)
} else {
moveTo(curIndex - 1)
}
}
function toRight() {
if (curIndex === count - 1) {
doms.carousel.style.transform = `translateX(100%)`
doms.carousel.style.transition = 'none'
// 这里添加强制渲染是为了有过渡效果
doms.carousel.clientWidth // 强制渲染
moveTo(0)
} else {
moveTo(curIndex + 1)
}
}
function initEvents() {
doms.indicators.forEach((item, index) => {
item.onclick = () => {
moveTo(index)
}
})
doms.leftArrow.onclick = () => toLeft()
doms.rightArrow.onclick = () => toRight()
}
function initCarousel() {
// 复制第一张图
const first = doms.carousel.firstElementChild.cloneNode(true)
// 复制最后一张图
const last = doms.carousel.lastElementChild.cloneNode(true)
// 将第一张图复制到末尾
doms.carousel.appendChild(first)
// 将最后一张图复制到开头
doms.carousel.insertBefore(last, doms.carousel.firstElementChild)
// 需要看到仍是第一张图
// 设置最后一张复制图为绝对定位
last.style.position = "absolute"
last.style.transform = `translateX(-100%)`
}
initCarousel()
initEvents()
效果图:
转载自:https://juejin.cn/post/7254834316018303033