1

Суть проблемы: Мне необходимо расположить несколько слайдеров на одной странице. Примерно понимаю как это можно сделать, но написать код не могу, не до конца разобрался во всем. Как я понимаю эти слайдеры должны быть одного класса, но с разными id. При этом каждый слайдер обрабатывается одной и той же функцией, которая двигает слайды с тем id, что и у кнопки.(каждый слайдер работает независимо от остальных слайдеров)

Слайдер желательно на чистом js и с комментариями как у меня, чтобы я хоть что-то понял:)

// Берём кнопку вперёд
let btnNext = document.querySelector("#btnNext");
// Берём слайды
let slides = document.querySelectorAll(".slide");
// Объявляем переменную i
let i = 0;

// Объявляем событие нажатия на кнопку вперёд btnNext.addEventListener("click", function() {

// Увеличиваем переменную i ++i // Условие если переменная i больше или равна количеству слайдов if (i >= slides.length) { // Удаляем класс block предыдущему слайду slides[i - 1].classList.remove("block"); // Присваиваем переменной i ноль i = 0; // Добавляем класс block следующему слайду slides[i].classList.add("block"); } else { // Иначе // Удаляем класс block предыдущему слайду slides[i - 1].classList.remove("block"); // Добавляем класс block следующему слайду slides[i].classList.add("block");

} })

.slides {
  width: 1000px;
  height: 500px;
}

img {
  display: none;
}

.block {
  display: block;
  object-fit: cover;
  width: 100%;
  height: 100%;
}
<!DOCTYPE html>
<html lang="en">

<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">
  <link rel="stylesheet" href="style.css" type="text/css">
  <title>Слайдер</title>
</head>

<body>
  <div class="slider">
    <div class="slides" id="sl0">
      <img src="" style="background: blue;" class="slide block" id="sl0" alt="">
      <img src="" style="background: red;" class="slide" id="sl0" alt="">
      <img src="" style="background: green;" class="slide" id="sl0" alt="">
    </div>
    <button id="btnNext" id="sli0">NEXT</button>
  </div>
  <div class="slider">
    <div class="slides" id="sl1">
      <img src="" style="background: blue;" class="slide block" id="sl1" alt="">
      <img src="" style="background: red;" class="slide" id="sl1" alt="">
      <img src="" style="background: green;" class="slide" id="sl1" alt="">
    </div>
    <button class="btnNext" id="sli1">NEXT</button>
  </div>
  <script src="app.js" class="btnNext" id="sl1"></script>
</body>

</html>

Просьба за глупости сильно не ругать, зеленый еще)

Danil Zimin
  • 57
  • 1
  • 8

2 Answers2

4

Не-а, не обязательно использовать разные id. Наоборот, можно написать универсальный код, используя названия классов, который будет работать с любым количеством слайдеров.

...желательно с комментариями...

let sliders = document.querySelectorAll('.slider');
// sliders - список всех элементов с классом class="slider"
// sliders[0] — первый элемент, sliders[1] — второй, sliders[i] — i-тый.

for (let i = 0; i < sliders.length; i++) { // Перебирает все, вызывает функцию для каждого. init_slider(sliders[i]); }

function init_slider(slider) { // Значение slider: Очередной sliders[i], переданный при вызове функции.

let slide = slider.querySelectorAll('.slide'); // Вместо document.query... Получается список всех class="slide" // которые находятся где-то внутри текущего элемента slider.

let next = slider.querySelector('.next'); // Кнопка next внутри этого slider.

let i = 0; // Номер текущего "открытого" слайда.

next.addEventListener('click', function() { slide[i].classList.remove('block'); // slide[i] - открытый слайд. Скрываем.

i = (i + 1) % slide.length; // (*1)

slide[i].classList.add('block');
// slide[i] - следующий слайд. Показываем.

});
}

body {
  display: flex;
}

.slides {
  width: 100px;
  height: 100px;
}

img {
  display: none;
}

.block {
  display: block;
  object-fit: cover;
  width: 100px;
  height: 100px;
}
<div class="slider">
  <div class="slides">
    <img style="background: blue;" class="slide block">
    <img style="background: red;" class="slide">
    <img style="background: green;" class="slide">
  </div>
  <button class="next">NEXT</button>
</div>

<div class="slider">
  <div class="slides">
    <img style="background: blue;" class="slide block">
    <img style="background: red;" class="slide">
    <img style="background: green;" class="slide">
  </div>
  <button class="next">NEXT</button>
</div>

(*1) i = (i + 1) % slide.length;a % b дает остаток от деления a на b.

В этом примере slide.length == 3, получается:

                                                     i было | стало
(0 + 1) % 3  →  1   // 1 не делится на 3            ||    0       1
(1 + 1) % 3  →  2   // 2 не делится на 3            ||    1       2
(2 + 1) % 3  →  0   // 3 делится на 3, остаток - 0. ||    2       0

... зацикливается, и без if-else :)


>> Книги и учебные ресурсы по JavaScript

OPTIMUS PRIME
  • 27,121
2

Можно отталкиваться от нажатого эл-та.

Сразу немного о "магии" используемой далее в коде, а конкретно о строке

currentIndex = [...slides].indexOf(block.querySelector('.slide.block'));

[] - обозначает массив (практически, это new Array() в сокращенном виде)

... - так называемый, оператор расширения (читать тут), вкратце, он говорит нам "добавить/извлечь в массив все эл-ты". Не путать с остаточными параметрами!

Суммируя, мы берём все найденные слайды (slides) и извлекаем их в массив, ну а дальше уже ищем индекс эл-та в массиве, используя indexOf()

// Берём все кнопки "вперёд"
let buttons = document.querySelectorAll("button.btnNext");

// циклом проходимся по каждой кнопке buttons.forEach(function (button) { // Объявляем событие нажатия на кнопку вперёд button.addEventListener("click", function(evt) { // находим "блок" слайдера let block = evt.target.closest('.slider'), // для ранее найденного блока берём все слайды slides = block.querySelectorAll('.slide'), // находим индекс активного слайда currentIndex = [...slides].indexOf(block.querySelector('.slide.block')); // находим индекс следующего слайда // если текущий слайд последний - начинаем "с нуля" nextIndex = currentIndex < (slides.length-1) ? currentIndex+1 : 0; // удаляем класс у текущего слайда slides[currentIndex].classList.remove("block"); // добавляем класс следующему слайду slides[nextIndex].classList.add("block"); }) });

.slides {
  width: 1000px;
  height: 500px;
}

img {
  display: none;
}

.block {
  display: block;
  object-fit: cover;
  width: 100%;
  height: 100%;
}
<div class="slider">
  <div class="slides" id="sl0">
    <img src="" style="background: blue;" class="slide " id="sl0" alt="">
    <img src="" style="background: red;" class="slide " id="sl0" alt="">
    <img src="" style="background: green;" class="slide block" id="sl0" alt="">
  </div>
  <button class="btnNext" id="sli0">NEXT</button>
</div>
<div class="slider">
  <div class="slides" id="sl1">
    <img src="" style="background: blue;" class="slide block" id="sl1" alt="">
    <img src="" style="background: red;" class="slide" id="sl1" alt="">
    <img src="" style="background: green;" class="slide" id="sl1" alt="">
  </div>
  <button class="btnNext" id="sli1">NEXT</button>
</div>
<script src="app.js" class="btnNext" id="sl1"></script>

P.S. ВАЖНО! Не может быть у одного эл-та несколько одинаковых атрибутов (у Вас, <button id="btnNext" id="sli0">NEXT</button>), так же, не может быть одинаковых id на странице (у Вас - всё тот же button с id="btnNext")

InDevX
  • 5,004