Swiper JS пролистывает не до конца
Недавно начал изучать вёрстку, но столкнулся с такой проблемой:
На десктопной версии всё работает отлично, а вот при ширине <992px, где отображается один слайд, слайдер листается криво.

HTML
<section id="objects" class="objects">
<div class="container">
<div class="objects-content">
<h2 class="title title-center">Примеры наших объектов</h2>
<div class="swiper-wrapper">
<div class="swiper-slide">
<img class="slide__image" src="/img/objects/1.jpg" alt="image" />
<h4 class="slide__name">Название объекта</h4>
</div>
<div class="swiper-slide">
<img class="slide__image" src="/img/objects/2.jpg" alt="image" />
<h4 class="slide__name">Название объекта</h4>
</div>
<div class="swiper-slide">
<img class="slide__image" src="/img/objects/3.jpg" alt="image" />
<h4 class="slide__name">Название объекта</h4>
</div>
</div>
</div>
</div>
</section
CSS
.objects {
overflow: hidden;
margin-bottom: 220px;
&-content {
overflow: hidden;
width: 100%;
}
}
.swiper {
max-width: 100%;
max-height: 350px;
&-wrapper {
height: 410px;
width: 100%;
}
&-slide {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
}
.slide {
&__image {
width: 100%;
height: 100%;
object-fit:cover;
}
&__name {
font-weight: 600;
color: #073F6D;
}
}
.title {
&-center {
text-align: center;
}
}
JS
new Swiper('.objects-content', {
grabCursor: true,
spaceBetween: 30,
loop: true,
slidesPerView: 3,
autoplay: {
delay: 3000,
disableOnInteraction: false,
}
});
window.addEventListener('resize', move);
function move(){
const viewport_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
if (viewport_width <= 992) {
new Swiper('.objects-content', {
slidesPerView: 1,
});
}
}
move();
Буду максимально благодарен за помощь :)
Ответы (1 шт):
Я предполагаю, что ошибочное поведение которое Вы наблюдаете связано с утечкой памяти и созданием нескольких экземпляров одновременно, да еще и с разными опциями.
В вашем случае swiper создается бесконтрольно — т.е. нет ни его уничтожения, ни контроля за количеством экземпляров, что порождает утечку памяти, привожу скрин в качестве доказательства где память вырасла с 2.63mb до 7.48mb:
Дело в том что библиотека SwiperJS не предполагает что компонент cлайдер будет пересоздаваться (у них в документации он объявляется через const т.е. константой), хотя в API библиотеки присутствует метод для уничтожения экземпляра слайдера как раз для Вашего случая:
swiper.destroy(deleteInstance, cleanStyles)
уничтожает экземпляр slider и отписывается от всех слушателей событий
Применение этого метода перед созданием нового экземпляра позволяет избежать утечки памяти, что видно на следующем скрине память возвращается к 2.51mb:
Сам код, если его не сильно рефакторить и оставить приблизительно в том же виде будет выглядеть так:
let perView = 3 // текущее количество слайдов на странице
function createSwiper(slidesPerView){
return new Swiper('.objects-content', {
grabCursor: true,
spaceBetween: 30,
loop: true,
slidesPerView,
autoplay: {
delay: 3000,
disableOnInteraction: false,
}
});
}
let swiper = createSwiper(perView)
window.addEventListener('resize', resize);
function resize(){
const viewport_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
if (viewport_width <= 992 && perView === 3) {
perView = 1 // было 3 делаем 1 — нужен экземпляр
swiper.destroy(); // уничтожаем предыдущий экземпляр
swiper = createSwiper(perView) // создаем новый
} else if ( viewport_width > 992 && perView === 1) {
perView = 3 // было 1 делаем 3 — нужен экземпляр
swiper.destroy(); // уничтожаем предыдущий экземпляр
swiper = createSwiper(perView) // создаем новый
}
}
resize();
Тут я завел отдельную переменную perView, для того чтобы создавать экземпляр только в том случае когда он будет отличаться от текущего параметром отображаемых слайдов, если количество слайдов будет совпадать — нет смысла создавать новый экземпляр.
Вообще, для события resize лучше использовать debounce функцию которая позволяет обрабатывать его с некоторой задержкой а соответственно снизить нагрузку на браузер вычисления новых состояний. Подробнее можете почитать тут
Решение основанное на брекпоинтах:
breakpoints object
Позволяет установить разные параметры для разных контрольных точек (размеров экрана). В точках останова можно изменить не все параметры, а только те, которые не требуют другой верстки и логики, например slidesPerView, slidesPerGroup, spaceBetween, grid.rows. Такие параметры, как loop и effect, работать не будут — требуют пересоздания слайдера.
function createSwiper(selector, slidesPerViewMin, slidesPerViewMax){
return new Swiper(selector, {
grabCursor: true,
spaceBetween: 30,
loop: true,
slidesPerView: slidesPerViewMin,
autoplay: {
delay: 3000,
disableOnInteraction: false,
},
breakpoints: {
992: {
slidesPerView: slidesPerViewMax
}
}
});
}
const swiper = createSwiper('.objects-content', 1, 3)
Пример в исходниках гитхаба

