123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- import React, { useRef, useState } from 'react';
- import './Slider.css';
- interface SliderProps {
- children: React.ReactNode;
- }
- function Slider({ children }: SliderProps) {
- const containerRef = useRef<HTMLDivElement>(null);
- const imageRef = useRef<HTMLDivElement>(null);
- const [isDragging, setIsDragging] = useState(false);
- const [startPosition, setStartPosition] = useState(0);
- const [currentTranslate, setCurrentTranslate] = useState(0);
- const [prevTranslate, setPrevTranslate] = useState(0);
- const [animationId, setAnimationId] = useState<number | null>(null);
- const [minTranslate, setMinTranslate] = useState(0);
- const [maxTranslate, setMaxTranslate] = useState(0);
- const startDragging = (event: any) => {
- if (event.type === 'touchstart') {
- setStartPosition(event.touches[0].clientX);
- } else {
- setStartPosition(event.clientX);
- }
- setIsDragging(true);
- cancelAnimationFrame(animationId!);
- };
- const dragging = (event: any) => {
- if (isDragging) {
- let currentPosition = 0;
- if (event.type === 'touchmove') {
- currentPosition = event.touches[0].clientX;
- } else {
- currentPosition = event.clientX;
- }
- const diff = currentPosition - startPosition;
- const newTranslate = prevTranslate + diff;
- const newMinTranslate = containerRef.current!.offsetWidth - imageRef.current!.offsetWidth;
- const newMaxTranslate = 0;
- if (newTranslate < newMinTranslate) {
- setCurrentTranslate(newMinTranslate);
- } else if (newTranslate > newMaxTranslate) {
- setCurrentTranslate(newMaxTranslate);
- } else {
- setCurrentTranslate(newTranslate);
- }
- }
- };
- const stopDragging = () => {
- setIsDragging(false);
- if (currentTranslate < minTranslate) {
- setCurrentTranslate(minTranslate);
- } else if (currentTranslate > maxTranslate) {
- setCurrentTranslate(maxTranslate);
- }
- setPrevTranslate(currentTranslate);
- setAnimationId(requestAnimationFrame(() => {
- imageRef.current!.style.transition = 'transform 0.3s ease-out';
- imageRef.current!.style.transform = `translateX(${currentTranslate}px)`;
- }));
- };
- const updateBoundaries = () => {
- if (containerRef.current && imageRef.current) {
- const containerWidth = containerRef.current.offsetWidth;
- const imageWidth = imageRef.current.offsetWidth;
- setMinTranslate(containerWidth - imageWidth);
- setMaxTranslate(0);
- }
- };
- return (
- <div
- className="slider-container"
- ref={containerRef}
- onMouseDown={startDragging}
- onTouchStart={startDragging}
- onMouseUp={stopDragging}
- onTouchEnd={stopDragging}
- onMouseLeave={stopDragging}
- onMouseMove={dragging}
- onTouchMove={dragging}
- onWheel={(event) => {
- event.preventDefault();
- setCurrentTranslate((prevTranslate) => {
- const scrollDistance = event.deltaY * -1;
- const maxScrollDistance = maxTranslate - prevTranslate;
- const minScrollDistance = minTranslate - prevTranslate;
- const scrollAmount =
- scrollDistance > 0
- ? Math.min(scrollDistance, maxScrollDistance)
- : Math.max(scrollDistance, minScrollDistance);
- return prevTranslate + scrollAmount;
- });
- }}
- onResize={updateBoundaries}
- >
- <div className="slider-con" ref={imageRef}>
- {children}
- </div>
- </div>
- );
- }
- export default Slider;
|