Как сделать бесконечную карусель?
Такой вопрос часто задают, но ответа я не нашёл. Сделать карусель легко, но бесконечную и без использования современных css-свойст сложно. Бесконечная карусель базируеться на добавление или дублирование элементов. Для прокрутки используют transition либо left. Но основная проблема заключаеться в потере плавности при добавления/удаление элементов для бесконечной прокрутки. Что можете посоветовать для решение такой проблемы ?
let left = document.getElementById("arrowLeft");
let right = document.getElementById("arrowRight");
let carusel = document.getElementById("carusel");
left.addEventListener("click", clickLeft);
right.addEventListener("click", clickRight);
const caruselElem = 3;
const width = 100 / caruselElem;
const item = carusel.children.length - caruselElem;
let current = 0;
for (let i = 0; i < carusel.childElementCount; i++) {
carusel.children[i].style.minWidth = width + "%";
}
function clickLeft() {
current -= 1;
if (current < 0) {
current = item;
}
carusel.style.transform = `translateX(-${width * current}%)`;
}
function clickRight() {
current += 1;
if (current > item) {
current = 0;
}
carusel.style.transform = `translateX(-${width * current}%)`;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
main {
display: flex;
align-items: center;
background: #0e38b1;
}
nav {
overflow-x: hidden;
}
div {
display: flex;
transition: 0.5s;
}
img {
object-fit: cover;
aspect-ratio: 16/9;
}
i {
padding: 10px;
font-size: 50px;
color: #ffffff;
cursor: pointer;
}
<body>
<main>
<i class="fas fa-chevron-left" id="arrowLeft"><</i>
<nav>
<div id="carusel">
<img
src="https://static-cse.canva.com/blob/846923/photo1502082553048f009c37129b9e1583341920812.jpeg"
/>
<img
src="https://white-rainbow.ru/upload/resize_cache/iblock/b26/7sf66d03tagu4tqpxywzr9e18325c05v/600_400_1/BSA_3747_Pano_copy.750.jpg"
/>
<img
src="https://i.pinimg.com/originals/be/39/7c/be397c91b8026b17f5f8a6ed98e23e9e.jpg"
/>
<img
src="https://s0.rbk.ru/v6_top_pics/media/img/6/76/756602873502766.jpg"
/>
<img
src="https://i.pinimg.com/originals/be/39/7c/be397c91b8026b17f5f8a6ed98e23e9e.jpg"
/>
<img
src="https://pibig.info/uploads/posts/2021-06/1623997495_14-pibig_info-p-priroda-solntse-priroda-krasivo-foto-16.jpg"
/>
</div>
</nav>
<i class="fas fa-chevron-right" id="arrowRight">></i>
</main>
</body>
Конечно можно использовать swiper - но для такой мелочи странно использовать целую библиотеку.
Ответы (1 шт):
Описание
Я бы предпочел немного хитрый подход. Я бы создал цикличный список, который бы вернул мне элемент под любым индексом, даже отрицательным и бы сгенерировал так чтобы показалось это как бесконечный карусель.
Решение
Я не напишу код полностью, вместо этого дам вам ключевые моменты.
Структура
Вот так, собственно, выглядит структура этого списка.
/**
* @template T
*/
class LoopedList {
/** @type {T[]} */ #items = [];
get period() {
return this.#items.length;
}
/**
* @param {number} index
* @returns {T}
*/
get(index) {
index %= this.period;
if (index < 0) index += this.period;
return this.#items[index];
}
/**
* @param {number} index
* @param {T} value
*/
set(index, value) {
index %= this.period;
if (index < 0) index += this.period;
this.#items[index] = value;
}
/**
* @param {T} value
*/
add(value) {
this.#items.push(value);
}
/**
* @param {T} value
*/
delete(value) {
const index = this.#items.indexOf(value);
if (index > 0) {
this.#items.splice(index, 1);
}
}
}
Методы add и delete будут работать напямую с массивом, а get и set создадут "эффект бесконечности".
Использование
И вот таким простым способом его можно использовать
/** @type {LoopedList<string>} */ const listSources = new LoopedList();
listSources.add(`ссылка 1`);
listSources.add(`ссылка 2`);
listSources.add(`ссылка 3`);
let index = 0;
buttonPrevious.addEventListener(`click`, (event) => {
img.src = listSources.get(--index);
});
buttonNext.addEventListener(`click`, (event) => {
img.src = listSources.get(++index);
});
Вам надо будет немного поработать над анимациями, рендерингом и будеть вам решение.
Плавность и прокрутка
Как, собственно, создать плавный переход?
У вас будут 2 кнопки - для прокрутки назад и вперед. Решение симетричное поэтому, решим для одного.
Как только пользователь жмет кнопку "Вперед" (к примеру) вы создаете элемент <img> справа от текущего, задаете src следующую ссылку, потом оба элемента плавно идут влево и как только предыдущий <img> уходит за завесы, вы удаляйте его.
Так у вас всегда будет всего несколько <img>, в центре будет текущая картинка и все будет происходить плавно, без сбоев.