Skip to content

Commit

Permalink
feat(freeMode): init (#4240)
Browse files Browse the repository at this point in the history
  • Loading branch information
vltansky authored Jul 11, 2021
1 parent c469d29 commit 895da28
Show file tree
Hide file tree
Showing 22 changed files with 346 additions and 295 deletions.
26 changes: 26 additions & 0 deletions cypress/integration/modules/free-mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference types="cypress" />

context('FreeMode', () => {
beforeEach(() => {
cy.swiperPage();
});

it('freeMode', () => {
cy.initSwiper({
freeMode: {
enabled: true,
},
});
cy.swipeLeft();
cy.getActiveSlide().should(($el) => {
expect($el[0].offsetLeft).to.be.greaterThan(800);
});
});
// it('freeModeMinimumVelocity', () => {});
// it('freeModeMomentum', () => {});
// it('freeModeMomentumBounce', () => {});
// it('freeModeMomentumBounceRatio', () => {});
// it('freeModeMomentumRatio', () => {});
// it('freeModeMomentumVelocityRatio', () => {});
// it('freeModeSticky', () => {});
});
1 change: 1 addition & 0 deletions scripts/build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = {
'effect-flip',
'effect-coverflow',
'thumbs',
'free-mode',
'slides-per-column',
],
themeColor: '#007aff',
Expand Down
7 changes: 0 additions & 7 deletions src/angular/src/swiper.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,6 @@ export class SwiperComponent implements OnInit {
@Input() edgeSwipeDetection: boolean | string;
@Input() edgeSwipeThreshold: number;
@Input() freeMode: SwiperOptions['freeMode'];
@Input() freeModeMomentum: SwiperOptions['freeModeMomentum'];
@Input() freeModeMomentumRatio: SwiperOptions['freeModeMomentumRatio'];
@Input() freeModeMomentumBounce: SwiperOptions['freeModeMomentumBounce'];
@Input() freeModeMomentumBounceRatio: SwiperOptions['freeModeMomentumBounceRatio'];
@Input() freeModeMomentumVelocityRatio: SwiperOptions['freeModeMomentumVelocityRatio'];
@Input() freeModeSticky: SwiperOptions['freeModeSticky'];
@Input() freeModeMinimumVelocity: SwiperOptions['freeModeMinimumVelocity'];
@Input() autoHeight: SwiperOptions['autoHeight'];
@Input() setWrapperSize: SwiperOptions['setWrapperSize'];
@Input() virtualTranslate: SwiperOptions['virtualTranslate'];
Expand Down
7 changes: 0 additions & 7 deletions src/angular/src/utils/params-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ export const paramsList = [
'_edgeSwipeDetection',
'_edgeSwipeThreshold',
'_freeMode',
'_freeModeMomentum',
'_freeModeMomentumRatio',
'_freeModeMomentumBounce',
'_freeModeMomentumBounceRatio',
'_freeModeMomentumVelocityRatio',
'_freeModeSticky',
'_freeModeMinimumVelocity',
'_autoHeight',
'setWrapperSize',
'virtualTranslate',
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/classes/addClasses.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function addClasses() {
'initialized',
params.direction,
{ 'pointer-events': support.pointerEvents && !support.touch },
{ 'free-mode': params.freeMode },
{ 'free-mode': swiper.params.freeMode && params.freeMode.enabled },
{ 'autoheight': params.autoHeight },
{ 'rtl': rtl },
{ 'multirow': params.slidesPerColumn > 1 },
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/core-class.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ class Swiper {
swiper.updateSlidesClasses();
}
let translated;
if (swiper.params.freeMode) {
if (swiper.params.freeMode && swiper.params.freeMode.enabled) {
setTranslate();
if (swiper.params.autoHeight) {
swiper.updateAutoHeight();
Expand Down
10 changes: 0 additions & 10 deletions src/components/core/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ export default {
edgeSwipeDetection: false,
edgeSwipeThreshold: 20,

// Free mode
freeMode: false,
freeModeMomentum: true,
freeModeMomentumRatio: 1,
freeModeMomentumBounce: true,
freeModeMomentumBounceRatio: 1,
freeModeMomentumVelocityRatio: 1,
freeModeSticky: false,
freeModeMinimumVelocity: 0.02,

// Autoheight
autoHeight: false,

Expand Down
179 changes: 3 additions & 176 deletions src/components/core/events/onTouchEnd.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default function onTouchEnd(event) {
const swiper = this;
const data = swiper.touchEventsData;

const { params, touches, rtlTranslate: rtl, $wrapperEl, slidesGrid, snapGrid, enabled } = swiper;
const { params, touches, rtlTranslate: rtl, slidesGrid, enabled } = swiper;
if (!enabled) return;
let e = event;
if (e.originalEvent) e = e.originalEvent;
Expand Down Expand Up @@ -75,181 +75,8 @@ export default function onTouchEnd(event) {
return;
}

if (params.freeMode) {
if (currentPos < -swiper.minTranslate()) {
swiper.slideTo(swiper.activeIndex);
return;
}
if (currentPos > -swiper.maxTranslate()) {
if (swiper.slides.length < snapGrid.length) {
swiper.slideTo(snapGrid.length - 1);
} else {
swiper.slideTo(swiper.slides.length - 1);
}
return;
}

if (params.freeModeMomentum) {
if (data.velocities.length > 1) {
const lastMoveEvent = data.velocities.pop();
const velocityEvent = data.velocities.pop();

const distance = lastMoveEvent.position - velocityEvent.position;
const time = lastMoveEvent.time - velocityEvent.time;
swiper.velocity = distance / time;
swiper.velocity /= 2;
if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
swiper.velocity = 0;
}
// this implies that the user stopped moving a finger then released.
// There would be no events with distance zero, so the last event is stale.
if (time > 150 || now() - lastMoveEvent.time > 300) {
swiper.velocity = 0;
}
} else {
swiper.velocity = 0;
}
swiper.velocity *= params.freeModeMomentumVelocityRatio;

data.velocities.length = 0;
let momentumDuration = 1000 * params.freeModeMomentumRatio;
const momentumDistance = swiper.velocity * momentumDuration;

let newPosition = swiper.translate + momentumDistance;
if (rtl) newPosition = -newPosition;

let doBounce = false;
let afterBouncePosition;
const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
let needsLoopFix;
if (newPosition < swiper.maxTranslate()) {
if (params.freeModeMomentumBounce) {
if (newPosition + swiper.maxTranslate() < -bounceAmount) {
newPosition = swiper.maxTranslate() - bounceAmount;
}
afterBouncePosition = swiper.maxTranslate();
doBounce = true;
data.allowMomentumBounce = true;
} else {
newPosition = swiper.maxTranslate();
}
if (params.loop && params.centeredSlides) needsLoopFix = true;
} else if (newPosition > swiper.minTranslate()) {
if (params.freeModeMomentumBounce) {
if (newPosition - swiper.minTranslate() > bounceAmount) {
newPosition = swiper.minTranslate() + bounceAmount;
}
afterBouncePosition = swiper.minTranslate();
doBounce = true;
data.allowMomentumBounce = true;
} else {
newPosition = swiper.minTranslate();
}
if (params.loop && params.centeredSlides) needsLoopFix = true;
} else if (params.freeModeSticky) {
let nextSlide;
for (let j = 0; j < snapGrid.length; j += 1) {
if (snapGrid[j] > -newPosition) {
nextSlide = j;
break;
}
}

if (
Math.abs(snapGrid[nextSlide] - newPosition) <
Math.abs(snapGrid[nextSlide - 1] - newPosition) ||
swiper.swipeDirection === 'next'
) {
newPosition = snapGrid[nextSlide];
} else {
newPosition = snapGrid[nextSlide - 1];
}
newPosition = -newPosition;
}
if (needsLoopFix) {
swiper.once('transitionEnd', () => {
swiper.loopFix();
});
}
// Fix duration
if (swiper.velocity !== 0) {
if (rtl) {
momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
} else {
momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
}
if (params.freeModeSticky) {
// If freeModeSticky is active and the user ends a swipe with a slow-velocity
// event, then durations can be 20+ seconds to slide one (or zero!) slides.
// It's easy to see this when simulating touch with mouse events. To fix this,
// limit single-slide swipes to the default slide duration. This also has the
// nice side effect of matching slide speed if the user stopped moving before
// lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
// For faster swipes, also apply limits (albeit higher ones).
const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
if (moveDistance < currentSlideSize) {
momentumDuration = params.speed;
} else if (moveDistance < 2 * currentSlideSize) {
momentumDuration = params.speed * 1.5;
} else {
momentumDuration = params.speed * 2.5;
}
}
} else if (params.freeModeSticky) {
swiper.slideToClosest();
return;
}

if (params.freeModeMomentumBounce && doBounce) {
swiper.updateProgress(afterBouncePosition);
swiper.setTransition(momentumDuration);
swiper.setTranslate(newPosition);
swiper.transitionStart(true, swiper.swipeDirection);
swiper.animating = true;
$wrapperEl.transitionEnd(() => {
if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
swiper.emit('momentumBounce');
swiper.setTransition(params.speed);
setTimeout(() => {
swiper.setTranslate(afterBouncePosition);
$wrapperEl.transitionEnd(() => {
if (!swiper || swiper.destroyed) return;
swiper.transitionEnd();
});
}, 0);
});
} else if (swiper.velocity) {
swiper.updateProgress(newPosition);
swiper.setTransition(momentumDuration);
swiper.setTranslate(newPosition);
swiper.transitionStart(true, swiper.swipeDirection);
if (!swiper.animating) {
swiper.animating = true;
$wrapperEl.transitionEnd(() => {
if (!swiper || swiper.destroyed) return;
swiper.transitionEnd();
});
}
} else {
swiper.emit('_freeModeNoMomentumRelease');
swiper.updateProgress(newPosition);
}

swiper.updateActiveIndex();
swiper.updateSlidesClasses();
} else if (params.freeModeSticky) {
swiper.slideToClosest();
return;
} else if (params.freeMode) {
swiper.emit('_freeModeNoMomentumRelease');
}

if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
swiper.updateProgress();
swiper.updateActiveIndex();
swiper.updateSlidesClasses();
}
if (swiper.params.freeMode && params.freeMode.enabled) {
swiper.freeMode.onTouchEnd({ currentPos });
return;
}

Expand Down
14 changes: 2 additions & 12 deletions src/components/core/events/onTouchMove.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,8 @@ export default function onTouchMove(event) {
swiper.updateActiveIndex();
swiper.updateSlidesClasses();
}
if (params.freeMode) {
// Velocity
if (data.velocities.length === 0) {
data.velocities.push({
position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
time: data.touchStartTime,
});
}
data.velocities.push({
position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
time: now(),
});
if (swiper.params.freeMode && params.freeMode.enabled) {
swiper.freeMode.onTouchMove();
}
// Update progress
swiper.updateProgress(data.currentTranslate);
Expand Down
Loading

0 comments on commit 895da28

Please sign in to comment.