189 lines
5.1 KiB
JavaScript
189 lines
5.1 KiB
JavaScript
import {
|
|
nextTick
|
|
} from '../../shared/utils.js';
|
|
|
|
export default function Controller({
|
|
swiper,
|
|
extendParams,
|
|
on
|
|
}) {
|
|
extendParams({
|
|
controller: {
|
|
control: undefined,
|
|
inverse: false,
|
|
by: 'slide', // or 'container'
|
|
},
|
|
});
|
|
|
|
swiper.controller = {
|
|
control: undefined,
|
|
};
|
|
|
|
function LinearSpline(x, y) {
|
|
const binarySearch = (function search() {
|
|
let maxIndex;
|
|
let minIndex;
|
|
let guess;
|
|
return (array, val) => {
|
|
minIndex = -1;
|
|
maxIndex = array.length;
|
|
while (maxIndex - minIndex > 1) {
|
|
guess = (maxIndex + minIndex) >> 1;
|
|
if (array[guess] <= val) {
|
|
minIndex = guess;
|
|
} else {
|
|
maxIndex = guess;
|
|
}
|
|
}
|
|
return maxIndex;
|
|
};
|
|
})();
|
|
this.x = x;
|
|
this.y = y;
|
|
this.lastIndex = x.length - 1;
|
|
let i1;
|
|
let i3;
|
|
|
|
this.interpolate = function interpolate(x2) {
|
|
if (!x2) return 0;
|
|
|
|
i3 = binarySearch(this.x, x2);
|
|
i1 = i3 - 1;
|
|
|
|
return (
|
|
((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1]
|
|
);
|
|
};
|
|
return this;
|
|
}
|
|
|
|
function getInterpolateFunction(c) {
|
|
swiper.controller.spline = swiper.params.loop ?
|
|
new LinearSpline(swiper.slidesGrid, c.slidesGrid) :
|
|
new LinearSpline(swiper.snapGrid, c.snapGrid);
|
|
}
|
|
|
|
function setTranslate(_t, byController) {
|
|
const controlled = swiper.controller.control;
|
|
let multiplier;
|
|
let controlledTranslate;
|
|
const Swiper = swiper.constructor;
|
|
|
|
function setControlledTranslate(c) {
|
|
if (c.destroyed) return;
|
|
|
|
const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
|
|
if (swiper.params.controller.by === 'slide') {
|
|
getInterpolateFunction(c);
|
|
|
|
controlledTranslate = -swiper.controller.spline.interpolate(-translate);
|
|
}
|
|
|
|
if (!controlledTranslate || swiper.params.controller.by === 'container') {
|
|
multiplier =
|
|
(c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
|
|
if (Number.isNaN(multiplier) || !Number.isFinite(multiplier)) {
|
|
multiplier = 1;
|
|
}
|
|
controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate();
|
|
}
|
|
|
|
if (swiper.params.controller.inverse) {
|
|
controlledTranslate = c.maxTranslate() - controlledTranslate;
|
|
}
|
|
c.updateProgress(controlledTranslate);
|
|
c.setTranslate(controlledTranslate, swiper);
|
|
c.updateActiveIndex();
|
|
c.updateSlidesClasses();
|
|
}
|
|
if (Array.isArray(controlled)) {
|
|
for (let i = 0; i < controlled.length; i += 1) {
|
|
if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
|
|
setControlledTranslate(controlled[i]);
|
|
}
|
|
}
|
|
} else if (controlled instanceof Swiper && byController !== controlled) {
|
|
setControlledTranslate(controlled);
|
|
}
|
|
}
|
|
|
|
function setTransition(duration, byController) {
|
|
const Swiper = swiper.constructor;
|
|
const controlled = swiper.controller.control;
|
|
let i;
|
|
|
|
function setControlledTransition(c) {
|
|
if (c.destroyed) return;
|
|
|
|
c.setTransition(duration, swiper);
|
|
if (duration !== 0) {
|
|
c.transitionStart();
|
|
if (c.params.autoHeight) {
|
|
nextTick(() => {
|
|
c.updateAutoHeight();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if (Array.isArray(controlled)) {
|
|
for (i = 0; i < controlled.length; i += 1) {
|
|
if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
|
|
setControlledTransition(controlled[i]);
|
|
}
|
|
}
|
|
} else if (controlled instanceof Swiper && byController !== controlled) {
|
|
setControlledTransition(controlled);
|
|
}
|
|
}
|
|
|
|
function removeSpline() {
|
|
if (!swiper.controller.control) return;
|
|
if (swiper.controller.spline) {
|
|
swiper.controller.spline = undefined;
|
|
delete swiper.controller.spline;
|
|
}
|
|
}
|
|
on('beforeInit', () => {
|
|
if (
|
|
typeof window !== 'undefined' && // eslint-disable-line
|
|
(typeof swiper.params.controller.control === 'string' ||
|
|
swiper.params.controller.control instanceof HTMLElement)
|
|
) {
|
|
const controlElement = document.querySelector(swiper.params.controller.control);
|
|
if (controlElement && controlElement.swiper) {
|
|
swiper.controller.control = controlElement.swiper;
|
|
} else if (controlElement) {
|
|
const onControllerSwiper = (e) => {
|
|
swiper.controller.control = e.detail[0];
|
|
swiper.update();
|
|
controlElement.removeEventListener('init', onControllerSwiper);
|
|
};
|
|
controlElement.addEventListener('init', onControllerSwiper);
|
|
}
|
|
return;
|
|
}
|
|
swiper.controller.control = swiper.params.controller.control;
|
|
});
|
|
on('update', () => {
|
|
removeSpline();
|
|
});
|
|
on('resize', () => {
|
|
removeSpline();
|
|
});
|
|
on('observerUpdate', () => {
|
|
removeSpline();
|
|
});
|
|
on('setTranslate', (_s, translate, byController) => {
|
|
if (!swiper.controller.control || swiper.controller.control.destroyed) return;
|
|
swiper.controller.setTranslate(translate, byController);
|
|
});
|
|
on('setTransition', (_s, duration, byController) => {
|
|
if (!swiper.controller.control || swiper.controller.control.destroyed) return;
|
|
swiper.controller.setTransition(duration, byController);
|
|
});
|
|
|
|
Object.assign(swiper.controller, {
|
|
setTranslate,
|
|
setTransition,
|
|
});
|
|
} |