Как центрировать новый активный слайд swiper?

Доброго времени суток.

Есть два свайпера, один управляет другим последством thumbs. Thumbs-слайдов больше. По событию "slideChangeTransitionStart" удаляю со всех thumbs классы -active, -prev, -next и вешаю на те , которые мне необходимы. В параметрах прописал centeredSlides: true и controller by container.

Я не могу отцентрировать новый активный слайд. Отслеживание по другим событиям не подходит. Мне нужно обновить параметры слайдера после назначения нового активного thumb'а, кто-нибудь знает как это можно сделать? или может есть другой путь? Буду благодарен за любую помощь.

historySlider.on("slideChangeTransitionStart", function () {

   // Get the active-slide when slide is changing
   let activeHistoryImage = document.querySelector(".history__slide.swiper-slide-active");

   // Get the active-slide data-slide attribute
   let activeHistoryImageAttr = activeHistoryImage.getAttribute("data-slide");

   let historyTimestamp = document.querySelectorAll(".history__stamp");

   // Get the cycle from timeline row
   historyTimestamp.forEach(item => {
      if (item.dataset.target == activeHistoryImageAttr) {
         let activeTimestamp = item;

         // Remove from any timeline slide active class
         historyTimestamp.forEach(elem => {
            elem.classList.remove("swiper-slide-active");
         });

         // Remove from any timeline slide prev class
         historyTimestamp.forEach(elem => {
            elem.classList.remove("swiper-slide-prev");
         });

         // Remove from any timeline slide next class
         historyTimestamp.forEach(elem => {
            elem.classList.remove("swiper-slide-next");
         });

         // Add active class to activeTimestamp, previous to previous and next to next
         activeTimestamp.classList.add("swiper-slide-active");
         activeTimestamp.previousElementSibling.classList.add("swiper-slide-prev");
         activeTimestamp.nextElementSibling.classList.add("swiper-slide-next");
      }
   });

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

Автор решения: Greg--

Я так понимаю просто нужно связать через API верхний с нижним, без обратного связывания?

Нижний слайдер стоит по центру, 4 мотоцикла в ряд, нижний слайдер меняется пли клике:

let bikeSwiper = new Swiper(".motorbike", {
  slidesPerView: 4,
  spaceBetween: 30,
})
let yearsSwiper = new Swiper(".years", {
  centeredSlides: true,
  slidesPerView: 3,
  spaceBetween: 30,
})

let bike = document.querySelectorAll(".motorbike .swiper-slide")
bike.forEach(element => {
  element.addEventListener("click", (event) => {
    yearsSwiper.slideTo(event.target.dataset.id, 300)
  })
})
body {
  height: 100%;
}

.swiper {
  margin-top: 20px;
}

.swiper-wrapper {
  width: 100%;
  height: 400px;
  position: relative;
}

.swiper-slide {
  width: 40%;
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
  border: 1px solid black;
  cursor: pointer;
}
<link href="https://unpkg.com/swiper@7/swiper-bundle.min.css" rel="stylesheet" />
<script src="https://unpkg.com/swiper@7/swiper-bundle.min.js"></script>

<div class="motorbike swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide" data-id="0">B1<br/>1980</div>
    <div class="swiper-slide" data-id="0">B2<br/>1982</div>
    <div class="swiper-slide" data-id="1">B3<br/>1985</div>
    <div class="swiper-slide" data-id="2">B4<br/>1990</div>
    <div class="swiper-slide" data-id="2">B5<br/>1992</div>
    <div class="swiper-slide" data-id="3">B6<br/>1995</div>
    <div class="swiper-slide" data-id="4">B7<br/>2000</div>
    <div class="swiper-slide" data-id="5">B8<br/>2005</div>
  </div>
</div>

<div class="years swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">1980 - 1984</div>
    <div class="swiper-slide">1985 - 1989</div>
    <div class="swiper-slide">1990 - 1994</div>
    <div class="swiper-slide">1995 - 1999</div>
    <div class="swiper-slide">2000 - 2004</div>
    <div class="swiper-slide">2005 - 2009</div>
  </div>
</div>

Но скорее всего вы хотите что то типа такого: один в ряд и автоматическая смена нижних слайдов при смене верхних.

let bikeSwiper = new Swiper(".motorbike", {
  slidesPerView: 1,
  spaceBetween: 30,
  on: {
    slideChange: (s) => {
      yearsSwiper.slideTo(s.slides[s.activeIndex].dataset.id, 300)
    }
  }
})
let yearsSwiper = new Swiper(".years", {
  centeredSlides: true,
  slidesPerView: 3,
  spaceBetween: 30,
})
* {
  padding: 0;
  margin: 0;
}

body {
  height: 100%;
}

.swiper {
  margin-top: 20px;
}

.swiper-wrapper {
  width: 100%;
  height: 400px;
  position: relative;
}

.swiper-slide {
  width: 80%;
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
  border: 1px solid black;
  cursor: pointer;
}
<link href="https://unpkg.com/swiper@7/swiper-bundle.min.css" rel="stylesheet" />
<script src="https://unpkg.com/swiper@7/swiper-bundle.min.js"></script>

<div class="motorbike swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide" data-id="0">B1<br/>1980</div>
    <div class="swiper-slide" data-id="0">B2<br/>1982</div>
    <div class="swiper-slide" data-id="1">B3<br/>1985</div>
    <div class="swiper-slide" data-id="2">B4<br/>1990</div>
    <div class="swiper-slide" data-id="2">B5<br/>1992</div>
    <div class="swiper-slide" data-id="3">B6<br/>1995</div>
    <div class="swiper-slide" data-id="4">B7<br/>2000</div>
    <div class="swiper-slide" data-id="5">B8<br/>2005</div>
  </div>
</div>

<div class="years swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">1980 - 1984</div>
    <div class="swiper-slide">1985 - 1989</div>
    <div class="swiper-slide">1990 - 1994</div>
    <div class="swiper-slide">1995 - 1999</div>
    <div class="swiper-slide">2000 - 2004</div>
    <div class="swiper-slide">2005 - 2009</div>
  </div>
</div>

Если почитать документацию по Методам и Событиям все становится достаточно просто.

Данные примеры можно как угодно масштабировать, главное придумать логику как получить id нужного слайда в соседнем слайдере

Обратите внимание в документации упоминается что если включить зацикливание слайдера то swiper.activeIndex индекс будет не совсем правильный, но есть параметр swiper.realIndex который поможет разобраться с индексами

→ Ссылка
Автор решения: Олег Олегов

После долгих экспериментов ответ был найден. Спасибо за помощь greg. Собственно, проблема заключалась в том, что слайды изображений генерировались через virtualSlides, а отследить их индекс не представляется возможным через методы API. Вот здесь я нашел человека, который столкнулся с такой же проблемой и воспользовался его решением. У каждого слайда с изображением мотоцикла есть дата атрибут с годом его производства, и у слайдов в ленте с годами у каждого слайда есть атрибут с годом.

  1. Нахожу активный слайд с моциком, считываю его дата атрибут.
  2. Прохожусь по ленте годов циклом, считываю атрибуты. Если дата атрибуты совпадают, нахожу индекс нужного года в ленте.
  3. Методом slideTo для ленты годов присваиваю новый активный слайд.
on: {
    beforeTransitionStart: (e) => {
    
      // Put in variable activeSlide the real active slide
      let activeSlide;
      let slides = e.slides;
      slides.forEach(item => {
        if (item.classList.contains("swiper-slide-active")) {
          activeSlide = item;
        }
      });
    
      // Find out dataset of the slide
      let activeSlideYear = activeSlide.dataset.slide;
    
      let stamps = document.querySelectorAll(".history__stamp");
      stamps = Array.from(stamps);
    
      // Put in variable targetStamp the real target stamp
      let targetStamp;
      stamps.forEach(item => {
        if (item.dataset.target == activeSlideYear) {
          targetStamp = item;
        }
      });
    
      // Find out index of the target stamp
      let targetStampIndex = stamps.indexOf(targetStamp);
    
      if (targetStampIndex > 0) {
        historyTimeline.slideTo(targetStampIndex);
      }
    }
→ Ссылка