Здесь я в основном рассказываю об идеях реализации карусели и плавной прокрутки, причем буду использовать самую простую карусель.Конечно, способов ее реализации множество, и это лишь один из них.
Примерная структура простой карусели такова: посередине расположены картинки, стрелки с двух сторон можно использовать для переключения картинок, а маленькие точки внизу тоже можно использовать для переключения картинок.
1. Простой эффект карусели
Сначала создайте структуру HTML
Здесь я использую значок svg для стрелок влево и вправо.
<div class="container">
<div class="carousel">
<div class="item"><a href=""><img src="./3.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./2.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./1.jpg" alt=""></a></div>
</div>
<div class="left">
<svg t="1693569521007" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4000" width="20" height="20">
<path
d="M729.6 931.2l-416-425.6 416-416c9.6-9.6 9.6-25.6 0-35.2-9.6-9.6-25.6-9.6-35.2 0l-432 435.2c-9.6 9.6-9.6 25.6 0 35.2l432 441.6c9.6 9.6 25.6 9.6 35.2 0C739.2 956.8 739.2 940.8 729.6 931.2z"
p-id="4001"></path>
</svg>
</div>
<div class="right">
<svg t="1693569535119" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4245" width="16" height="16">
<path
d="M761.6 489.6l-432-435.2c-9.6-9.6-25.6-9.6-35.2 0-9.6 9.6-9.6 25.6 0 35.2l416 416-416 425.6c-9.6 9.6-9.6 25.6 0 35.2s25.6 9.6 35.2 0l432-441.6C771.2 515.2 771.2 499.2 761.6 489.6z"
p-id="4246"></path>
</svg>
</div>
<div class="indicator">
<span class="active"></span>
<span></span>
<span></span>
</div>
</div>
а затем стиль CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 700px;
height: 400px;
margin: 10px auto;
overflow: hidden;
position: relative;
}
.container .carousel {
width: 100%;
height: 100%;
display: flex;
}
.container .carousel .item img {
width: 700px;
height: 400px;
}
.container .indicator {
height: 30px;
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
}
.container .indicator span {
border: 1px solid #fff;
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
}
.container .indicator span.active {
background-color: pink;
}
.container .left {
position: absolute;
left: 10px;
top: 50%;
}
.container .right {
position: absolute;
right: 10px;
top: 50%;
}
Ключевой код CSS — overflow:hidden, гибкий эластичный блок, который я открыл здесь, используйте его, чтобы скрыть лишние изображения, а затем добавьте активный элемент к одному из элементов круга.
Ниже приведен js-код
Сначала нам нужно получить все элементы dom
var doms = {
carousel: document.querySelector('.carousel'),
indicator: document.querySelectorAll('.indicator span'),
left: document.querySelector('.left'),
right: document.querySelector('.right')
}
Самое главное — функция карусели
var curIndex = 0 //用于记录当前是第几个元素
function moveTo(index) {
//加上动画效果
doms.carousel.style.transition = 'transform .5s'
doms.carousel.style.transform = `translateX(-${index}00%)`
//去除效果
var active = document.querySelector('.indicator span.active')
active.classList.remove('active')
//选中当前效果
doms.indicator[index].classList.add('active')
curIndex = index
}
Здесь я использую TranslateX (-100%) Transform, чтобы реализовать переключение карусели, или использую поле слева, чтобы управлять им.
Далее вы можете добавить таймер для управления автоматическим вращением.
//添加图片自动轮播
let timer = setInterval(() => {
if (curIndex === doms.indicator.length - 1) {
moveTo(0)
} else (
moveTo(curIndex + 1)
)
}, 2000)
Вы также можете добавить соответствующие события кликов к маленькому кругу и стрелкам влево и вправо ниже.
//添加点击事件
doms.indicator.forEach((item, index) => {
item.addEventListener('click', () => {
moveTo(index)
})
})
//添加点击事件
doms.left.addEventListener('click', () => {
moveTo(curIndex-1)
})
doms.right.addEventListener('click', () => {
moveTo(curIndex+1)
})
На данный момент реализованы основные функции простой карты-карусели, но она не идеальна, и будут эффекты стабилизации и плавной прокрутки.
2. Плавная прокрутка и защита от тряски.
Идея плавной прокрутки заключается в использовании функции клонирования и изменении эффекта анимации для достижения
Точно так же скопируйте последний и поместите его вперед, но он по-прежнему показывает 1.jpg, а первую копию поместите в конец.
При переключении на последний или первый сначала отключите чрезмерную анимацию, а затем быстро включите чрезмерную анимацию для поворота к следующей, чтобы глаза не могли ее обнаружить, потому что скорость очень быстрая.
Во-первых, это клонирование
//克隆图片,实现无缝滚动
function clone() {
var first = doms.carousel.firstElementChild.cloneNode(true);
//复制最后一张
var 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%)`
}
clone()
Ключом к клонированию является изменение положения первого изображения клона.
Затем реализуйте плавную прокрутку стрелки вправо.
//实现右边的无缝滚动
var count = doms.indicator.length
function rightMove() {
//首先去除动画效果
if (curIndex === count - 1) {
doms.carousel.style.transform = `translateX(100%)`;
doms.carousel.style.transition = 'none';
//强制渲染,否则可能不会执行
doms.carousel.clientHeight;
moveTo(0)
} else {
moveTo(curIndex + 1)
}
}
После того, как правая часть реализована, левая часть становится очень простой.
//实现左边的无缝滚动
function leftMove() {
if (curIndex === 0) {
doms.carousel.style.transform = `translateX(-${count}00%)`;
doms.carousel.style.transition = 'none';
//强制渲染
doms.carousel.clientHeight;
moveTo(count - 1)
} else {
moveTo(curIndex - 1)
}
}
Тогда наш таймер нужно изменить, чтобы он мог вращаться вправо».
//添加图片自动轮播
let timer = setInterval(() => {
rightMove()
}, 2000)
Затем выполните антитряску там, где нужна антитряска.На самом деле, моя очень простая антитряска - это выключить таймер, а затем включить таймер после завершения задачи по клику.
//添加点击事件
doms.indicator.forEach((item, index) => {
item.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
moveTo(index)
//执行完后开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
})
Нажмите на событие со стрелками влево и вправо
//添加点击事件
doms.left.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
leftMove()
//开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
doms.right.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
rightMove()
//开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
На этом этапе реализуется простой эффект изображения карусели.
Общий код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 700px;
height: 400px;
margin: 10px auto;
overflow: hidden;
position: relative;
}
.container .carousel {
width: 100%;
height: 100%;
display: flex;
/* transition: .5s; */
}
.container .carousel .item img {
width: 700px;
height: 400px;
}
.container .indicator {
height: 30px;
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
}
.container .indicator span {
/* background-color: #fff; */
border: 1px solid #fff;
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
}
.container .indicator span.active {
background-color: pink;
}
.container .left {
position: absolute;
left: 10px;
top: 50%;
}
.container .right {
position: absolute;
right: 10px;
top: 50%;
}
</style>
</head>
<body>
<div class="container">
<div class="carousel">
<div class="item"><a href=""><img src="./3.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./2.jpg" alt=""></a></div>
<div class="item"><a href=""><img src="./1.jpg" alt=""></a></div>
</div>
<div class="left">
<svg t="1693569521007" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4000" width="20" height="20">
<path
d="M729.6 931.2l-416-425.6 416-416c9.6-9.6 9.6-25.6 0-35.2-9.6-9.6-25.6-9.6-35.2 0l-432 435.2c-9.6 9.6-9.6 25.6 0 35.2l432 441.6c9.6 9.6 25.6 9.6 35.2 0C739.2 956.8 739.2 940.8 729.6 931.2z"
p-id="4001"></path>
</svg>
</div>
<div class="right">
<svg t="1693569535119" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4245" width="16" height="16">
<path
d="M761.6 489.6l-432-435.2c-9.6-9.6-25.6-9.6-35.2 0-9.6 9.6-9.6 25.6 0 35.2l416 416-416 425.6c-9.6 9.6-9.6 25.6 0 35.2s25.6 9.6 35.2 0l432-441.6C771.2 515.2 771.2 499.2 761.6 489.6z"
p-id="4246"></path>
</svg>
</div>
<div class="indicator">
<span class="active"></span>
<span></span>
<span></span>
</div>
</div>
</body>
<script>
var doms = {
carousel: document.querySelector('.carousel'),
indicator: document.querySelectorAll('.indicator span'),
left: document.querySelector('.left'),
right: document.querySelector('.right')
}
var curIndex = 0
function moveTo(index) {
//加上动画效果
doms.carousel.style.transition = 'transform .5s'
doms.carousel.style.transform = `translateX(-${index}00%)`
//去除效果
var active = document.querySelector('.indicator span.active')
active.classList.remove('active')
//选中当前效果
doms.indicator[index].classList.add('active')
curIndex = index
}
//添加点击事件
doms.indicator.forEach((item, index) => {
item.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
moveTo(index)
//执行完后开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
})
//添加图片自动轮播
let timer = setInterval(() => {
rightMove()
}, 2000)
//克隆图片,实现无缝滚动
function clone() {
var first = doms.carousel.firstElementChild.cloneNode(true);
//复制最后一张
var 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%)`
}
clone()
//实现右边的无缝滚动
var count = doms.indicator.length
function rightMove() {
//首先去除动画效果
if (curIndex === count - 1) {
doms.carousel.style.transform = `translateX(100%)`;
doms.carousel.style.transition = 'none';
//强制渲染
doms.carousel.clientHeight;
moveTo(0)
} else {
moveTo(curIndex + 1)
}
}
//实现左边的无缝滚动
function leftMove() {
if (curIndex === 0) {
doms.carousel.style.transform = `translateX(-${count}00%)`;
doms.carousel.style.transition = 'none';
//强制渲染
doms.carousel.clientHeight;
moveTo(count - 1)
} else {
moveTo(curIndex - 1)
}
}
//添加点击事件
doms.left.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
leftMove()
//开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
doms.right.addEventListener('click', () => {
//关闭定时器
clearInterval(timer)
rightMove()
//开启定时器
timer = setInterval(() => {
rightMove()
}, 2000)
})
</script>
</html>