Add scrolling carousel

master
Hasan Genc 5 years ago
parent f43229d96a
commit e02372f748
  1. 4
      src/components/carousel/index.tsx
  2. 46
      src/components/scrolling-carousel/index.tsx
  3. 10
      src/helpers/index.ts
  4. 4
      src/index.ts

@ -51,7 +51,9 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
isSliding: true, isSliding: true,
}); });
setCurrent(next); setCurrent(next);
setShowArrow(getShowArrow(props.children.length, props.show, props.infinite, next)); setShowArrow(
getShowArrow(props.children.length, props.show, props.infinite, next),
);
setTimeout(() => { setTimeout(() => {
if (props.infinite) { if (props.infinite) {
setItems(cleanItems(rotated, slide, direction)); setItems(cleanItems(rotated, slide, direction));

@ -7,8 +7,9 @@ import React, {
} from 'react'; } from 'react';
import { Item, SlideDirection } from '../../types/carousel'; import { Item, SlideDirection } from '../../types/carousel';
import styles from '../../styles/slider/styles.module.css'; import styles from '../../styles/slider/styles.module.css';
import { getOuterWidth } from '../../helpers';
export const Slider: FunctionComponent<SliderProps> = ({ export const ScrollingCarousel: FunctionComponent<SliderProps> = ({
children, children,
className, className,
}: SliderProps) => { }: SliderProps) => {
@ -31,11 +32,16 @@ export const Slider: FunctionComponent<SliderProps> = ({
}; };
const [showArrow, setShowArrow] = useState<Arrows>(showArrows()); const [showArrow, setShowArrow] = useState<Arrows>(showArrows());
const onScroll = (_: Event) => {
setShowArrow(showArrows());
};
const ref = useCallback( const ref = useCallback(
(node) => { (node) => {
if (node !== null) { if (node !== null) {
Object.defineProperty(slider, 'current', { value: node }); Object.defineProperty(slider, 'current', { value: node });
setShowArrow(showArrows()); setShowArrow(showArrows());
node.addEventListener('scroll', onScroll);
} }
}, },
[slider], [slider],
@ -64,11 +70,36 @@ export const Slider: FunctionComponent<SliderProps> = ({
slider.current!.scrollLeft = position.scrollLeft - slide; slider.current!.scrollLeft = position.scrollLeft - slide;
}; };
const calculateSlideAmount = (direction: SlideDirection): number => {
const _slider = slider.current!;
const currentView =
direction === SlideDirection.Left
? _slider.scrollLeft + _slider.offsetWidth
: _slider.scrollLeft;
const childNodes = Array.from(_slider.children) as HTMLElement[];
let nodeWidthSum = 0;
for (const node of childNodes) {
const nodeWidth = getOuterWidth(node);
nodeWidthSum += nodeWidth;
if (nodeWidthSum >= currentView) {
const showingPart =
direction === SlideDirection.Left
? nodeWidthSum - currentView
: nodeWidth;
return (_slider.offsetWidth - showingPart) * direction;
}
}
return _slider.offsetWidth;
};
const slide = (direction: SlideDirection) => { const slide = (direction: SlideDirection) => {
const slideAmount = -1 * direction * slider.current!.offsetWidth * 0.9; const slideAmount = calculateSlideAmount(direction);
const start = slider.current!.scrollLeft; const start = slider.current!.scrollLeft;
smoothHorizontalScroll(500, slideAmount, start); smoothHorizontalScroll(500, slideAmount, start);
setShowArrow(showArrows());
}; };
const smoothHorizontalScroll = (time: number, amount: number, start: number) => { const smoothHorizontalScroll = (time: number, amount: number, start: number) => {
@ -85,16 +116,19 @@ export const Slider: FunctionComponent<SliderProps> = ({
const smoothHorizontalScrollBehavior = (amount: number) => { const smoothHorizontalScrollBehavior = (amount: number) => {
slider.current!.scrollLeft = amount; slider.current!.scrollLeft = amount;
setShowArrow(showArrows());
}; };
return ( return (
<div className={`${styles.sliderBase} ${className}`}> <div className={`${styles.sliderBase} ${className}`}>
{showArrow.left && ( {showArrow.left && (
<button onClick={() => slide(SlideDirection.Left)}>left</button> <div data-arrow="left">
<button onClick={() => slide(SlideDirection.Right)} />
</div>
)} )}
{showArrow.right && ( {showArrow.right && (
<button onClick={() => slide(SlideDirection.Right)}>right</button> <div data-arrow="right">
<button onClick={() => slide(SlideDirection.Left)} />
</div>
)} )}
<div <div
ref={ref} ref={ref}

@ -133,3 +133,13 @@ export function getPageX(e: TouchEvent | MouseEvent): number {
} }
return 0; return 0;
} }
export function getOuterWidth(el: HTMLElement) {
const style = getComputedStyle(el);
return (
el.offsetWidth +
(parseInt(style.marginLeft, 10) || 0) +
(parseInt(style.marginRight, 10) || 0)
);
}

@ -1,4 +1,4 @@
import { Carousel } from './components/carousel'; import { Carousel } from './components/carousel';
import { Slider } from './components/slider'; import { ScrollingCarousel } from './components/scrolling-carousel';
export { Carousel, Slider }; export { Carousel, ScrollingCarousel };

Loading…
Cancel
Save