filter fix

This commit is contained in:
2024-05-02 11:32:35 +05:00
parent 17aea1fff1
commit ce6d660bd2
8 changed files with 4549 additions and 230 deletions
@@ -0,0 +1,225 @@
/* eslint-disable react-hooks/exhaustive-deps */
import gsap from "gsap";
import { useState, useEffect } from "react";
import { isMobile } from "react-device-detect";
import { useSwipeable } from "react-swipeable";
import { Transition } from "react-transition-group";
// const marks = [
// {
// id: "1",
// label: "Башня 1",
// icon: "tower1",
// x: [1210, 1095, 770, 660, 820, 1060],
// y: [675, 795, 790, 670, 590, 590],
// url: "/tower1",
// },
// {
// id: "2",
// label: "Башня 2",
// icon: "tower2",
// x: [650, 835, 1080, 1240, 1080, 720],
// y: [650, 565, 575, 670, 800, 780],
// url: "/tower2",
// },
// {
// id: "3",
// label: "Двор",
// icon: "walk",
// x: [930, 930, 930, 930, 930, 930],
// y: [930, 930, 930, 930, 930, 930],
// url: "/virtual-tour",
// },
// {
// id: "4",
// label: "Внешний двор",
// icon: "walk",
// x: [1310, 980, 600, -100, -100, 1185],
// y: [1075, 1280, 1130, -100, -100, 860],
// url: "/virtual-tour-2",
// },
// ];
const arrayLength = 360;
interface SequenceSliderProps {
path: string;
}
function SequenceSlider({ path }: SequenceSliderProps) {
const [selectedImageRightIndex, setSelectedRightImageIndex] =
useState<number>(0);
const [selectedImageLeftIndex, setSelectedImageLeftIndex] =
useState<number>(0);
const [isAnimate, setIsAnimate] = useState<boolean>(false);
const keyframes: number[] = [0, 60, 120, 180, 240, 300];
const [keyframeIndex, setKeyframeIndex] = useState<number>(0);
const handlers = useSwipeable({
trackMouse: true,
onSwipedLeft: () => !isAnimate && next(),
onSwipedRight: () => !isAnimate && prev(),
});
const [loadedImages, setLoadedImages] = useState<number>(0);
function handleLoad() {
setLoadedImages((prev) => prev + 1);
}
function animateToRight() {
const obj = { selectedImageIndex: selectedImageRightIndex };
gsap.to(obj, {
selectedImageIndex: selectedImageRightIndex + 60,
duration: 0.75,
ease: "power1.inOut",
onUpdate: () => {
const roundedIndex = Math.round(obj.selectedImageIndex);
if (roundedIndex === arrayLength) {
setSelectedRightImageIndex(0);
setSelectedImageLeftIndex(0);
} else {
setSelectedRightImageIndex(roundedIndex);
setSelectedImageLeftIndex(arrayLength - roundedIndex);
}
},
onComplete: () => {
setIsAnimate(false);
},
});
}
function animateToLeft() {
const obj = { selectedImageIndex: selectedImageLeftIndex };
gsap.to(obj, {
selectedImageIndex: selectedImageLeftIndex + 60,
duration: 0.75,
ease: "power1.inOut",
onUpdate: () => {
const roundedIndex = Math.round(obj.selectedImageIndex);
if (roundedIndex === arrayLength || roundedIndex === 0) {
setSelectedRightImageIndex(0);
setSelectedImageLeftIndex(0);
} else {
setSelectedImageLeftIndex(roundedIndex);
setSelectedRightImageIndex(arrayLength - roundedIndex);
}
},
onComplete: () => {
setIsAnimate(false);
},
});
}
function next() {
setIsAnimate(true);
animateToRight();
}
function prev() {
setIsAnimate(true);
animateToLeft();
}
useEffect(() => {
if (keyframes.includes(selectedImageRightIndex)) {
console.log(setKeyframeIndex(keyframes.indexOf(selectedImageRightIndex)));
}
}, [selectedImageRightIndex]);
const [width, setWidth] = useState<number>();
const [top, setTop] = useState<number>();
function handleResize() {
setWidth(window.innerWidth);
setTop(window.innerWidth / 2 - window.innerHeight / 2);
}
useEffect(() => {
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return (
<div
{...handlers}
className="scene absolute w-full h-full overflow-hidden bg-black"
>
<div
className="absolute left-0"
style={{ width: `${width}px`, height: `${width}px`, top: `-${top}px` }}
>
{Array.from({ length: arrayLength }).map((_, index) => (
<>
<img
key={index}
width={`${width}px`}
height={`${width}px`}
src={`${path}/${index + 1}.${isMobile ? "jpg" : "jpg"}`}
alt=""
className={`absolute t select-none pointer-events-none ${
index === selectedImageRightIndex ? "opacity-100" : "opacity-0"
}`}
onLoad={handleLoad}
/>
</>
))}
</div>
<button
disabled={isAnimate}
className={`p-3 bg-[#0079C2] hover:bg-[#0069A8] rounded-full transition-colors absolute left-6 top-[calc(50%-24px)] z-50 ${
isAnimate ? "opacity-50" : "opacity-100"
}`}
onClick={prev}
>
{/* <ChevronLeftIcon /> */}
</button>
<button
disabled={isAnimate}
className={`p-3 bg-[#0079C2] hover:bg-[#0069A8] rounded-full transition-all absolute right-6 top-[calc(50%-24px)] z-50 ${
isAnimate ? "opacity-50" : "opacity-100"
}`}
onClick={next}
>
{/* <ChevronRightIcon /> */}
</button>
<div
className="absolute left-0 z-40 select-none"
style={{ width: `${width}px`, height: `${width}px`, top: `-${top}px` }}
>
<div
className={`transition-opacity duration-75 ${
keyframes.includes(selectedImageRightIndex)
? "opacity-100"
: "opacity-0"
}`}
>
{/* <MainMarksContainer marks={marks} keyframeIndex={keyframeIndex} /> */}
</div>
</div>
<Transition
in={loadedImages !== arrayLength}
timeout={300}
mountOnEnter
unmountOnExit
>
{(state) => (
<div
className={`absolute top-0 left-0 w-full h-full flex items-center justify-center bg-neutral-950 z-50 transition-opacity duration-300 ${state}`}
>
<h2 className="text-2xl font-tenor text-white whitespace-nowrap">
Загрузка... {Math.round((100 / arrayLength) * loadedImages)} %
</h2>
</div>
)}
</Transition>
</div>
);
}
export default SequenceSlider;