dressed_for_succes_store/components/Hero.tsx

136 lines
4.4 KiB
TypeScript

import { useState, useEffect } from "react";
import Image from "next/image";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
// Типы для свойств компонента
interface HeroProps {
images?: string[];
}
export default function Hero({ images = [] }: HeroProps) {
// Состояние для текущего индекса слайда
const [currentIndex, setCurrentIndex] = useState(0);
// Состояние для автоматического воспроизведения
const [autoplay, setAutoplay] = useState(true);
// Состояние для направления анимации: 1 - следующий слайд, -1 - предыдущий слайд
const [direction, setDirection] = useState(0);
// Если изображения не переданы или массив пуст, используем стандартное изображение
const heroImages = images.length > 0
? images
: ['/photos/head_photo.png'];
// Функция для перехода к следующему слайду
const nextSlide = () => {
setDirection(1);
setCurrentIndex((prevIndex) =>
prevIndex === heroImages.length - 1 ? 0 : prevIndex + 1
);
};
// Функция для перехода к предыдущему слайду
const prevSlide = () => {
setDirection(-1);
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? heroImages.length - 1 : prevIndex - 1
);
};
// Эффект для автоматического воспроизведения слайдера
useEffect(() => {
let interval: NodeJS.Timeout;
if (autoplay) {
interval = setInterval(() => {
nextSlide();
}, 5000); // Смена слайда каждые 5 секунд
}
return () => {
if (interval) clearInterval(interval);
};
}, [autoplay, currentIndex]);
// Определяем варианты анимации для эффекта "скольжения"
const variants = {
enter: (direction: number) => ({
x: direction > 0 ? "100%" : "-100%",
opacity: 0
}),
center: {
x: 0,
opacity: 1
},
exit: (direction: number) => ({
x: direction > 0 ? "-100%" : "100%",
opacity: 0
}),
};
return (
<div className="relative h-screen overflow-hidden">
<AnimatePresence custom={direction} mode="wait">
<motion.div
key={currentIndex}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{ duration: 0.7 }}
className="absolute inset-0"
>
<Image
src={heroImages[currentIndex]}
alt="New Arrivals"
layout="fill"
objectFit="cover"
quality={100}
priority
/>
{/* Убрали затемнение изображения */}
</motion.div>
</AnimatePresence>
<button
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-white bg-opacity-50 p-2 rounded-full hover:bg-opacity-70 transition-all"
onClick={() => {
prevSlide();
setAutoplay(false);
}}
>
<ChevronLeft className="w-6 h-6 text-black" />
</button>
<button
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-white bg-opacity-50 p-2 rounded-full hover:bg-opacity-70 transition-all"
onClick={() => {
nextSlide();
setAutoplay(false);
}}
>
<ChevronRight className="w-6 h-6 text-black" />
</button>
{/* Индикаторы слайдов */}
<div className="absolute bottom-8 left-0 right-0 flex justify-center space-x-2">
{heroImages.map((_, index) => (
<button
key={index}
onClick={() => {
// Определяем направление в зависимости от выбранного индекса
setDirection(index > currentIndex ? 1 : -1);
setCurrentIndex(index);
setAutoplay(false);
}}
className={`w-3 h-3 rounded-full ${
index === currentIndex ? 'bg-white' : 'bg-white/50'
}`}
/>
))}
</div>
</div>
);
}