Доработать слайдер на JS

Написал слайдер на чистом js (просто чтобы не пользоваться сторонними библиотеками)

function sliderLogic(sliderName, slideVisible, dots, buttons, autoPlay, timeAnimation, autoPlayTime) {

  const sliderWpar = document.querySelector(sliderName);
  const slider = sliderWpar.querySelector('.slider__line');
  const dotsWrapper = sliderWpar.querySelector('.dots');
  const buttonsWrapper = sliderWpar.querySelector('.buttons');
  const slides = sliderWpar.querySelectorAll('.slider__item');
  const slidesCount = slides.length;
  const sliderBoxWidth = sliderWpar.querySelector('.slider').offsetWidth;
  let slideWidth;
  let countMovie = 0;
  let dotCount = slidesCount - slideVisible + 1;
  let activeDot;

  if (autoPlay) {
    autoPlay = setInterval(function() {
      nextin(slideWidth);
    }, autoPlayTime);
  }

  slider.style.cssText = `
        position: relative;
        left: 0;
        display: flex;
        align-items: center; 
        transition: all ` + timeAnimation + `s ease-in;
      `

  slides.forEach(item => {
    slideWidth = sliderBoxWidth / slideVisible;
    item.style.width = slideWidth + 'px';
  });

  function goSlide(n) {
    countMovie = countMovie - n;
    if (countMovie < -((slideWidth * slides.length) - (slideVisible * slideWidth))) {
      countMovie = 0;
    }
    if (countMovie > 0) {
      countMovie = -(slideWidth * slides.length) - -(slideVisible * slideWidth);
    }
    dotsElems.forEach(elem => {
      elem.classList.remove('active');
    });
    activeDot = countMovie / -slideWidth;
    if (dots) {
      dotsElems[activeDot].classList.add('active');
    }
    slider.style.left = countMovie + 'px';
  }

  function nextin(n) {
    goSlide(n);
  }

  function previous(n) {
    goSlide(-n);
  }

  if (dots) {
    let dot = '';
    for (let i = 0; i < dotCount; i++) {
      dot += '<span class="dots__item"></span>'
    }
    dotsWrapper.innerHTML = dot;
  }

  let dotsElems = sliderWpar.querySelectorAll('.dots__item');
  dotsElems.forEach((item, i) => {
    if (countMovie == 0) {
      dotsElems[0].classList.add('active');
    }
    item.addEventListener('click', function() {
      clearInterval(autoPlay);
      dotsElems.forEach(elem => {
        elem.classList.remove('active');
      });
      this.classList.add('active');
      countMovie = 0 - (i * slideWidth);
      slider.style.left = countMovie + 'px';
    });
  });

  if (buttons) {
    const nextButton = document.createElement('button');
    nextButton.classList.add('next');
    nextButton.innerText = 'next';
    const prevButton = document.createElement('button');
    prevButton.classList.add('prev');
    prevButton.innerText = 'prev';

    buttonsWrapper.append(prevButton, nextButton);

    nextButton.addEventListener('click', () => {
      nextin(slideWidth);
      clearInterval(autoPlay);
    });
    prevButton.addEventListener('click', () => {
      previous(slideWidth);
      clearInterval(autoPlay);
    });
  }

}
// sliderLogic(селектор обертки слайдера, кол-во видимых слайдов, показывать точки или нет, показывать кнопки или нет, включить автопрокрутку или нет, время анимации прокрутки слайдов, интервал автопрокрутки)
sliderLogic('.wrapper', 2, true, true, false, 1, 1000);
sliderLogic('.wrapper-2', 4, true, true, true, 0.5, 1000);
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper,
.wrapper-2 {
  width: 800px;
  margin: 0 0 30px 0;
}

.slider {
  width: 100%;
  margin: 0 0 20px 0;
  border: 1px solid;
  overflow: hidden;
  box-sizing: border-box;
}

.slider__item {
  flex-shrink: 0;
  padding: 5px;
  box-sizing: border-box;
}

.slider__item img {
  display: block;
  width: 100%;
}

.dots {
  margin: 30px 0;
}

.dots__item {
  width: 10px;
  height: 10px;
  margin: 5px 7px;
  padding: 0;
  display: inline-block;
  background: #bbb;
  border-radius: 5px;
  cursor: pointer;
}

.active {
  background: #000 !important;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Slider translate vanilla js</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <div class="wrapper">
    <div class="slider">
      <div class="slider__line">
        <div class="slider__item">
          <img src="https://tes-game.ru/_nw/14/08884847.jpg" alt="">1
        </div>
        <div class="slider__item">
          <img src="https://xage.ru/media/posts/2019/8/26/26-minutes-of-gameplay-dying-light-2-in-4k-trailer_BOLSTko.jpg" alt="">2
        </div>
        <div class="slider__item">
          <img src="https://free4kwallpapers.com/uploads/originals/2020/05/02/game-art-wallpaper.jpg" alt="">3
        </div>
        <div class="slider__item">
          <img src="https://images.hdqwalls.com/wallpapers/bthumb/resident-evil-2-2019-4k-5a.jpg" alt="">4
        </div>
        <div class="slider__item">
          <img src="https://gamespot1.cbsistatic.com/uploads/screen_kubrick/1406/14063904/3477799-7716868968-far-c.jpg" alt="">5
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">6
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">7
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">8
        </div>
      </div>
    </div>
    <div class="dots"></div>
    <div class="buttons"></div>
  </div>

  <div class="wrapper-2">
    <div class="slider">
      <div class="slider__line">
        <div class="slider__item">
          <img src="https://tes-game.ru/_nw/14/08884847.jpg" alt="">1
        </div>
        <div class="slider__item">
          <img src="https://xage.ru/media/posts/2019/8/26/26-minutes-of-gameplay-dying-light-2-in-4k-trailer_BOLSTko.jpg" alt="">2
        </div>
        <div class="slider__item">
          <img src="https://free4kwallpapers.com/uploads/originals/2020/05/02/game-art-wallpaper.jpg" alt="">3
        </div>
        <div class="slider__item">
          <img src="https://images.hdqwalls.com/wallpapers/bthumb/resident-evil-2-2019-4k-5a.jpg" alt="">4
        </div>
        <div class="slider__item">
          <img src="https://gamespot1.cbsistatic.com/uploads/screen_kubrick/1406/14063904/3477799-7716868968-far-c.jpg" alt="">5
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">6
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">7
        </div>
        <div class="slider__item">
          <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">8
        </div>
      </div>
    </div>
    <div class="dots"></div>
    <div class="buttons"></div>
  </div>

  <script src="script.js"></script>

</body>

</html>

Только вот не знаю как решить след. проблему.

Все опции для его работы я сделал параметрами и при объявлении функции прописываю для каждого слайдера отдельно(если, к примеру, их несколько на странице) - sliderLogic('.wrapper', 2, true, true, false, 1, 1000);

А мне хочется(да и удобнее так) сделать их отдельно опциями в самой функции, по типу как у слика того же

$('.slider-news').slick({
    infinite: true,
    slidesToShow: 3,
    slidesToScroll: 1,
    arrows: false,
    dots: true,
    speed: 1000,
    variableWidth: true,

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

Можете подсказать как это реализовать?


Ответы (1 шт):

Автор решения: Сергей Комыза

Благодаря помощи тут, немного доработал слайдер. Оставлю тут, если вдруг кому нужен будет простой слайдер на чистом js, без доп. библиотек

function sliderLogic(options){
  
const sliderWpar = document.querySelector(options.sliderName);
const slider = sliderWpar.querySelector('.slider__line');
const dotsWrapper = sliderWpar.querySelector('.dots');
const buttonsWrapper = sliderWpar.querySelector('.buttons');
const slides = sliderWpar.querySelectorAll('.slider__item');
const slidesCount = slides.length;
const sliderBoxWidth = sliderWpar.querySelector('.slider').offsetWidth;
let slideWidth; 
let countMovie = 0; 
let dotCount = slidesCount - options.slideVisible+1;
let activeDot;
let autoScroll;

if(options.autoPlay){
  autoScroll = setInterval(function(){
    nextin(slideWidth);
  }, options.autoPlayTime);
}
  
  slider.style.cssText = `
    position: relative;
    left: 0;
    display: flex;
    align-items: center; 
    transition: all `+options.timeAnimation+`s ease-in;
  `

  slides.forEach( item => {
    slideWidth = Math.round(sliderBoxWidth / options.slideVisible);
    item.style.width = slideWidth + 'px';
  });
  
function goSlide(n){
  countMovie = countMovie - n;
  if( countMovie < -( (slideWidth * slides.length) - (options.slideVisible * slideWidth) ) ){
    countMovie = 0;
  }
  if( countMovie > 0 ){
    countMovie = -(slideWidth * slides.length) - -(options.slideVisible * slideWidth);
  }
  dotsElems.forEach( elem => {
    elem.classList.remove('active');
  });
  activeDot = countMovie / -slideWidth;
  if( options.dots ){
    dotsElems[activeDot].classList.add('active');
  }
  slider.style.left = countMovie + 'px';
}
  
function nextin(n){
  goSlide(n);
}
function previous(n){
  goSlide(-n);
}
  
  if( options.dots ){
    let dot = '';
    for( let i = 0; i < dotCount; i++ ){
      dot += '<span class="dots__item"></span>'
    }
    dotsWrapper.innerHTML = dot;
  }
  
let dotsElems = sliderWpar.querySelectorAll('.dots__item');
  dotsElems.forEach( (item, i) => {
    if( countMovie == 0 ){
      dotsElems[0].classList.add('active');
    }
    item.addEventListener('click', function(){
      clearInterval(autoScroll);
      dotsElems.forEach( elem => {
        elem.classList.remove('active');
      });
      this.classList.add('active');
      countMovie = 0 - (i * slideWidth);
      slider.style.left = countMovie + 'px';
    });
  });

if(options.buttons){
  
  let sliderClassName = sliderWpar.className;
  
  const nextButton = document.createElement('button');
  nextButton.classList.add(''+sliderClassName+'__next');
  nextButton.innerText = 'next';
  const prevButton = document.createElement('button');
  prevButton.classList.add(''+sliderClassName+'__prev');
  prevButton.innerText = 'prev';
  
  buttonsWrapper.append(prevButton, nextButton);

  nextButton.addEventListener('click', function() {
    nextin(slideWidth);
    clearInterval(autoScroll);
  });
  
  prevButton.addEventListener('click', () => {
    previous(slideWidth);
    clearInterval(autoScroll);
  });
  
}
 
}

sliderLogic({
  sliderName: '.wrapper',
  slideVisible: 3, 
  dots: true, 
  buttons: false, 
  autoPlay: true, 
  timeAnimation: 1, 
  autoPlayTime: 2000
});

sliderLogic({
  sliderName: '.wrapper-2',
  slideVisible: 4, 
  dots: true, 
  buttons: true, 
  autoPlay: true, 
  timeAnimation: 1, 
  autoPlayTime: 2000
});
body{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper,
.wrapper-2{
  width: 800px;
  margin: 0 0 30px 0;
}

.slider{
  width: 100%;
  margin: 0 0 20px 0;
  border: 1px solid;
  overflow: hidden;
  box-sizing: border-box;
}

.slider__item{
  flex-shrink: 0;
  padding: 5px;
  box-sizing: border-box;
}

.slider__item img{
  display: block;
  width: 100%;
}

.dots{
  margin: 30px 0;
}

.dots__item{
  width: 10px;
  height: 10px;
  margin: 5px 7px;
  padding: 0;
  display: inline-block;
  background: #BBB;
  border-radius: 5px;
  cursor: pointer;
}

.active{
  background: #000 !important;
}
<div class="wrapper">
  <div class="slider">
    <div class="slider__line">
      <div class="slider__item">
        <img src="https://tes-game.ru/_nw/14/08884847.jpg" alt="">1
      </div>
      <div class="slider__item">
        <img src="https://xage.ru/media/posts/2019/8/26/26-minutes-of-gameplay-dying-light-2-in-4k-trailer_BOLSTko.jpg" alt="">2
      </div>
      <div class="slider__item">
        <img src="https://free4kwallpapers.com/uploads/originals/2020/05/02/game-art-wallpaper.jpg" alt="">3
      </div>
      <div class="slider__item">
        <img src="https://images.hdqwalls.com/wallpapers/bthumb/resident-evil-2-2019-4k-5a.jpg" alt="">4
      </div>
      <div class="slider__item">
        <img src="https://gamespot1.cbsistatic.com/uploads/screen_kubrick/1406/14063904/3477799-7716868968-far-c.jpg" alt="">5
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">6
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">7
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">8
      </div>
    </div>
  </div>
  <div class="dots"></div>
  <div class="buttons"></div>
</div>

 <div class="wrapper-2">
  <div class="slider">
    <div class="slider__line">
      <div class="slider__item">
        <img src="https://tes-game.ru/_nw/14/08884847.jpg" alt="">1
      </div>
      <div class="slider__item">
        <img src="https://xage.ru/media/posts/2019/8/26/26-minutes-of-gameplay-dying-light-2-in-4k-trailer_BOLSTko.jpg" alt="">2
      </div>
      <div class="slider__item">
        <img src="https://free4kwallpapers.com/uploads/originals/2020/05/02/game-art-wallpaper.jpg" alt="">3
      </div>
      <div class="slider__item">
        <img src="https://images.hdqwalls.com/wallpapers/bthumb/resident-evil-2-2019-4k-5a.jpg" alt="">4
      </div>
      <div class="slider__item">
        <img src="https://gamespot1.cbsistatic.com/uploads/screen_kubrick/1406/14063904/3477799-7716868968-far-c.jpg" alt="">5
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">6
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">7
      </div>
      <div class="slider__item">
        <img src="https://www.gametube.sk/wp-content/uploads/2016/11/Screenshot-10.12.2016-17_53_06.jpg" alt="">8
      </div>
    </div>
  </div>
  <div class="dots"></div>
  <div class="buttons"></div>
</div> 

https://codepen.io/sergo/pen/PozYbYj?editors=0010

→ Ссылка