filter fix
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import RangeSlider from "react-range-slider-input";
|
||||
// import "react-range-slider-input/dist/style.css";
|
||||
import "./multiRamgeSlider.css";
|
||||
@@ -12,24 +12,55 @@ interface MultiRangeSliderProps {
|
||||
const MultiRangeSlider = ({ min, max, onChange }: MultiRangeSliderProps) => {
|
||||
const [firstValue, setFirstValue] = useState(min);
|
||||
const [secondValue, setSecondValue] = useState(max);
|
||||
const firstInputRef = useRef(null);
|
||||
const secondInputRef = useRef(null);
|
||||
|
||||
const handleOnRangeInputChange = (e: [a: number, b: number]) => {
|
||||
setFirstValue(e[0]);
|
||||
setSecondValue(e[1]);
|
||||
};
|
||||
|
||||
const handleOnFirstInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = Number(e.target.value);
|
||||
if (value >= min && value <= max) {
|
||||
setFirstValue(value);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnSecondInputChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
const value = Number(e.target.value);
|
||||
if (value >= min && value <= max) {
|
||||
setSecondValue(value);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!firstInputRef.current) return;
|
||||
(firstInputRef.current as HTMLInputElement).focus();
|
||||
}, [firstValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!secondInputRef.current) return;
|
||||
(secondInputRef.current as HTMLInputElement).focus();
|
||||
}, [secondValue]);
|
||||
|
||||
return (
|
||||
<div className="px-2">
|
||||
<div className="flex justify-between p-3 bg-white rounded-2xl relative flex-col">
|
||||
<div className="flex justify-between">
|
||||
<input
|
||||
ref={firstInputRef}
|
||||
key={firstValue}
|
||||
type="number"
|
||||
onChange={(e) => console.log("e", e.target.value)}
|
||||
onChange={handleOnFirstInputChange}
|
||||
defaultValue={firstValue}
|
||||
className="focus:outline-none input_number"
|
||||
/>
|
||||
<input
|
||||
ref={secondInputRef}
|
||||
onChange={handleOnSecondInputChange}
|
||||
key={secondValue}
|
||||
type="number"
|
||||
defaultValue={secondValue}
|
||||
@@ -40,7 +71,7 @@ const MultiRangeSlider = ({ min, max, onChange }: MultiRangeSliderProps) => {
|
||||
min={min}
|
||||
max={max}
|
||||
value={[firstValue, secondValue]}
|
||||
className="absolute bottom-0 left-2 w-[calc(100%-16px)] z-20"
|
||||
className="absolute -bottom-3 left-0 w-[calc(100%-16px)] z-20"
|
||||
onInput={handleOnRangeInputChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -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;
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { FullScreen, useFullScreenHandle } from "react-full-screen";
|
||||
import { useEffect } from "react";
|
||||
import useModal from "../../../store/useModal";
|
||||
import DesktopHeader from "./DesktopHeader";
|
||||
import MobileHeader from "./MobileHeader";
|
||||
import useFullScreen from "../../../store/useFullScreen";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const Layout = () => {
|
||||
const { modal } = useModal();
|
||||
|
||||
@@ -13,11 +13,10 @@ interface ICheckbox {
|
||||
}
|
||||
|
||||
const checkboxes: ICheckbox[] = [
|
||||
{ title: "Studio Flex", id: "1", disabled: true },
|
||||
{ title: "Studio Flex", id: "1", disabled: false },
|
||||
{ title: "Studio", id: "2" },
|
||||
{ title: "1 Bedroom", id: "3" },
|
||||
{ title: "2 Bedroom, Type A", id: "4" },
|
||||
{ title: "2 Bedroom, Type B", id: "5" },
|
||||
{ title: "2 Bedroom", id: "4" },
|
||||
];
|
||||
|
||||
const MasterplanFilters = () => {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import ButtomPanel from "../components/ButtomPanel";
|
||||
import ComplexTopPanel from "../components/complexPage/ComplexTopPanel";
|
||||
import SequenceSlider from "../components/complexPage/SequenceSlider";
|
||||
|
||||
const Complex = () => {
|
||||
return (
|
||||
<div className="overflow-hidden h-screen w-screen">
|
||||
<ComplexTopPanel />
|
||||
<div className="bg-black h-full w-full"></div>
|
||||
{/* <SequenceSlider path={""} /> */}
|
||||
<ButtomPanel />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user