Skip to content

Commit

Permalink
feat(virtual): support loop mode with virtual slides
Browse files Browse the repository at this point in the history
  • Loading branch information
nolimits4web committed Dec 7, 2022
1 parent d23e809 commit f890f1e
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 40 deletions.
4 changes: 3 additions & 1 deletion src/core/events/onResize.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ export default function onResize() {
swiper.updateSlides();

swiper.updateSlidesClasses();
const isVirtualLoop = isVirtual && params.loop;
if (
(params.slidesPerView === 'auto' || params.slidesPerView > 1) &&
swiper.isEnd &&
!swiper.isBeginning &&
!swiper.params.centeredSlides
!swiper.params.centeredSlides &&
!isVirtualLoop
) {
swiper.slideTo(swiper.slides.length - 1, 0, false, true);
} else {
Expand Down
16 changes: 9 additions & 7 deletions src/core/loop/loopFix.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ export default function loopFix(slideRealIndex, slideTo = true) {
if (!swiper.params.loop) return;
swiper.emit('beforeLoopFix');

const { slides, allowSlidePrev, allowSlideNext, $slidesEl } = swiper;
const { slides, allowSlidePrev, allowSlideNext, $slidesEl, params } = swiper;

swiper.allowSlidePrev = true;
swiper.allowSlideNext = true;

if (swiper.virtual && swiper.params.virtual.enabled) {
if (swiper.virtual && params.virtual.enabled) {
if (slideTo) {
if (swiper.snapIndex === 0) {
if (!params.centeredSlides && swiper.snapIndex === 0) {
swiper.slideTo(swiper.virtual.slides.length, 0, false, true);
} else if (params.centeredSlides && swiper.snapIndex < params.slidesPerView) {
swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true);
} else if (swiper.snapIndex === swiper.snapGrid.length - 1) {
swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true);
}
Expand All @@ -23,12 +25,12 @@ export default function loopFix(slideRealIndex, slideTo = true) {
}

const slidesPerView =
swiper.params.slidesPerView === 'auto'
params.slidesPerView === 'auto'
? swiper.slidesPerViewDynamic()
: Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
: Math.ceil(parseFloat(params.slidesPerView, 10));
let loopedSlides = slidesPerView;
if (loopedSlides % swiper.params.slidesPerGroup !== 0) {
loopedSlides += swiper.params.slidesPerGroup - (loopedSlides % swiper.params.slidesPerGroup);
if (loopedSlides % params.slidesPerGroup !== 0) {
loopedSlides += params.slidesPerGroup - (loopedSlides % params.slidesPerGroup);
}
swiper.loopedSlides = loopedSlides;

Expand Down
1 change: 0 additions & 1 deletion src/core/slide/slideTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export default function slideTo(
if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;

const translate = -snapGrid[snapIndex];

// Normalize slideIndex
if (params.normalizeSlideIndex) {
for (let i = 0; i < slidesGrid.length; i += 1) {
Expand Down
5 changes: 4 additions & 1 deletion src/core/update/updateActiveIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ export default function updateActiveIndex(newActiveIndex) {
const getVirtualRealIndex = (aIndex) => {
let realIndex = aIndex - swiper.virtual.slidesBefore;
if (realIndex < 0) {
realIndex = swiper.virtual.slides.length - 1;
realIndex = swiper.virtual.slides.length + realIndex;
}
if (realIndex >= swiper.virtual.slides.length) {
realIndex -= swiper.virtual.slides.length;
}
return realIndex;
};
Expand Down
22 changes: 17 additions & 5 deletions src/core/update/updateSlides.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,23 @@ export default function updateSlides() {
}
}
if (isVirtual && params.loop) {
snapGrid.push(
snapGrid[snapGrid.length - 1] + slidesSizesGrid[0] + spaceBetween,
snapGrid[snapGrid.length - 1] + (slidesSizesGrid[0] + spaceBetween) * 2,
);
slidesGrid.push(slidesGrid[slidesGrid.length - 1] + slidesSizesGrid[0] + spaceBetween);
const size = slidesSizesGrid[0] + spaceBetween;
if (params.slidesPerGroup > 1) {
const groups = Math.ceil(
(swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup,
);
const groupSize = size * params.slidesPerGroup;
for (let i = 0; i < groups; i += 1) {
snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize);
}
}
for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) {
if (params.slidesPerGroup === 1) {
snapGrid.push(snapGrid[snapGrid.length - 1] + size);
}
slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size);
swiper.virtualSize += size;
}
}
if (snapGrid.length === 0) snapGrid = [0];

Expand Down
16 changes: 7 additions & 9 deletions src/modules/virtual/virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,21 @@ export default function Virtual({ swiper, extendParams, on, emit }) {
slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;
} else {
slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesAfter;
slidesBefore = slidesPerGroup + addSlidesBefore;
slidesBefore = (isLoop ? slidesPerView : slidesPerGroup) + addSlidesBefore;
}
let from = activeIndex - slidesBefore;
if (!isLoop) {
from = Math.max(from, 0);
}
if (activeIndex >= slidesBefore) {
// from -= 1;
}
let to = activeIndex + slidesAfter;
if (!isLoop) {
from = Math.max(from, 0);
to = Math.min(to, slides.length - 1);
}
let offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
if (activeIndex >= slidesBefore) {
if (isLoop && activeIndex >= slidesBefore) {
from -= slidesBefore;
offset += swiper.slidesGrid[0];
if (!centeredSlides) offset += swiper.slidesGrid[0];
} else if (isLoop && activeIndex < slidesBefore) {
from = -slidesBefore;
if (centeredSlides) offset += swiper.slidesGrid[0];
}

Object.assign(swiper.virtual, {
Expand Down
33 changes: 26 additions & 7 deletions src/react/virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,40 @@ import React from 'react';

function renderVirtual(swiper, slides, virtualData) {
if (!virtualData) return null;

const getSlideIndex = (index) => {
let slideIndex = index;
if (index < 0) {
slideIndex = slides.length + index;
} else if (slideIndex >= slides.length) {
// eslint-disable-next-line
slideIndex = slideIndex - slides.length;
}
return slideIndex;
};

const style = swiper.isHorizontal()
? {
[swiper.rtlTranslate ? 'right' : 'left']: `${virtualData.offset}px`,
}
: {
top: `${virtualData.offset}px`,
};
return slides
.filter((child, index) => index >= virtualData.from && index <= virtualData.to)
.map((child) => {
return React.cloneElement(child, {
swiper,
style,
});
const { from, to } = virtualData;
const loopFrom = swiper.params.loop ? -slides.length : 0;
const loopTo = swiper.params.loop ? slides.length * 2 : slides.length;
const slidesToRender = [];
for (let i = loopFrom; i < loopTo; i += 1) {
if (i >= from && i <= to) {
slidesToRender.push(slides[getSlideIndex(i)]);
}
}
return slidesToRender.map((child) => {
return React.cloneElement(child, {
swiper,
style,
});
});
}

export { renderVirtual };
35 changes: 26 additions & 9 deletions src/vue/virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,39 @@ import { h } from 'vue';

function renderVirtual(swiperRef, slides, virtualData) {
if (!virtualData) return null;
const getSlideIndex = (index) => {
let slideIndex = index;
if (index < 0) {
slideIndex = slides.length + index;
} else if (slideIndex >= slides.length) {
// eslint-disable-next-line
slideIndex = slideIndex - slides.length;
}
return slideIndex;
};
const style = swiperRef.value.isHorizontal()
? {
[swiperRef.value.rtlTranslate ? 'right' : 'left']: `${virtualData.offset}px`,
}
: {
top: `${virtualData.offset}px`,
};
return slides
.filter((slide, index) => index >= virtualData.from && index <= virtualData.to)
.map((slide) => {
if (!slide.props) slide.props = {};
if (!slide.props.style) slide.props.style = {};
slide.props.swiperRef = swiperRef;
slide.props.style = style;
return h(slide.type, { ...slide.props }, slide.children);
});
const { from, to } = virtualData;
const loopFrom = swiperRef.value.params.loop ? -slides.length : 0;
const loopTo = swiperRef.value.params.loop ? slides.length * 2 : slides.length;
const slidesToRender = [];
for (let i = loopFrom; i < loopTo; i += 1) {
if (i >= from && i <= to) {
slidesToRender.push(slides[getSlideIndex(i)]);
}
}
return slidesToRender.map((slide) => {
if (!slide.props) slide.props = {};
if (!slide.props.style) slide.props.style = {};
slide.props.swiperRef = swiperRef;
slide.props.style = style;
return h(slide.type, { ...slide.props }, slide.children);
});
}

export { renderVirtual };

0 comments on commit f890f1e

Please sign in to comment.