You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.0 KiB

5 years ago
import { MouseEvent, TouchEvent } from 'react';
import { SlideDirection, Item } from '../types/carousel';
export class Circular<T> {
constructor(private arr: T[], private currentIndex: number) {}
next(): T {
const i = this.currentIndex;
const arr = this.arr;
this.currentIndex = i < arr.length - 1 ? i + 1 : 0;
return this.current();
}
prev(): T {
const i = this.currentIndex;
const arr = this.arr;
this.currentIndex = i > 0 ? i - 1 : arr.length - 1;
return this.current();
}
current(): T {
return this.arr[this.currentIndex];
}
}
export const rotateItems = (
items: any[],
showingItems: any[],
start: number,
show: number,
slide: number,
direction: SlideDirection,
): any[] => {
const circular = new Circular(items, start);
const newItems: any[] = Array.from(showingItems);
switch (+direction) {
case SlideDirection.Left:
for (let i = slide; i >= 0; i--) {
if (slide - i < 0 || !newItems[i - slide]) {
newItems.unshift(circular.current());
}
circular.prev();
}
break;
case SlideDirection.Right:
for (let i = 0; i < show + slide; i++) {
if (!newItems[2 * slide + i]) {
newItems.push(circular.current());
}
circular.next();
}
break;
}
return newItems;
};
export const getTransformAmount = (
width: number,
slideCount: number,
direction: SlideDirection,
): number => {
return direction * width * slideCount;
};
export const getCurrent = (
current: number,
slide: number,
length: number,
direction: SlideDirection,
) => {
const slideTo = current - direction * slide;
if (slideTo < 0) {
return length + slideTo;
} else if (length <= slideTo) {
return slideTo - length;
}
return slideTo;
};
export const getShowArrow = (
items: number,
show: number,
infinite: boolean,
current: number,
): { left: boolean; right: boolean } => {
const isItemsMore = items > show;
if (infinite) {
return {
left: isItemsMore,
right: isItemsMore,
};
}
return {
left: isItemsMore && current !== 0,
right: isItemsMore && current + show < items,
};
};
export const cleanItems = (
showingItems: any[],
slide: number,
direction: SlideDirection,
): any[] => {
if (direction === SlideDirection.Left) {
return showingItems.slice(0, -1 * slide);
}
return showingItems.slice(slide);
};
export const initItems = (items: Item[], slide: number, infinite: boolean): Item[] => {
if (!infinite) {
return items;
}
const newArray = Array.from(items);
const circular = new Circular(items, 0);
for (let i = 0; i < slide; i++) {
newArray.unshift(circular.prev());
}
return newArray;
};
export function getPageX(e: TouchEvent | MouseEvent): number {
if (e.nativeEvent instanceof MouseEvent) {
return e.nativeEvent.pageX;
} else if (e.nativeEvent instanceof TouchEvent) {
return e.nativeEvent.changedTouches[0].pageX;
}
return 0;
}
export function getOuterWidth(el: HTMLElement) {
const style = getComputedStyle(el);
return (
el.offsetWidth +
(parseInt(style.marginLeft, 10) || 0) +
(parseInt(style.marginRight, 10) || 0)
);
}