This commit is contained in:
2024-04-11 12:31:29 +05:00
parent 7d38f02978
commit 3a1cfcefe0
42 changed files with 694 additions and 123 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 807 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

+7 -1
View File
@@ -19,7 +19,13 @@ function Button({
}`}
onClick={onClick}
>
<span className={`${iconOrderLast ? "order-last" : ""} ${widthFull ? "" : ""}`}>{icon}</span>
<span
className={`${iconOrderLast ? "order-last" : ""} ${
widthFull ? "" : ""
}`}
>
{icon}
</span>
<span>{text}</span>
</button>
);
@@ -16,7 +16,7 @@ const InfrastructureFilters = ({
selectedRange,
marks,
}: InfrastructureFiltersProps) => {
const [filter, setFilter] = useState("");
const [filter, setFilter] = useState("shop");
function handleOnFilterClick(
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
): void {
@@ -34,7 +34,6 @@ const InfrastructureFilters = ({
const filteredMarks = marks.filter(
(mark) => mark.icon === filter && mark.distance <= selectedRange
);
console.log("filteredMarks", filteredMarks);
setFilteredMarks(filteredMarks);
}, [selectedRange, filter, marks, setFilteredMarks]);
@@ -42,9 +41,12 @@ const InfrastructureFilters = ({
return (
<>
<div>
<h2 className="font-tenor text-2xl mb-8">Инфраструктура</h2>
<h3 className="text-[18px] mb-5">Окружение:</h3>
<div className="flex flex-col gap-2 mb-8 border-b border-[#9595A2] pb-8">
{/* <h2 className="font-tenor 2xl:text-2xl text-xl 2xl:mb-8 mb-5"> */}
<h2 className="font-tenor text-xl mb-5">Инфраструктура</h2>
{/* <h3 className="text-[18px] 2xl:mb-5 mb-3">Окружение:</h3> */}
<h3 className="text-[18px] mb-3">Окружение:</h3>
{/* <div className="flex flex-col 2xl:gap-2 gap-[6px] 2xl:mb-8 mb-5 border-b border-[#9595A2] 2xl:pb-8 pb-5"> */}
<div className="flex flex-col 2xl:gap-2 gap-[6px] mb-5 border-b border-[#9595A2] pb-5">
{environments.map((env) => (
<button
data-set={env.type}
@@ -54,15 +56,15 @@ const InfrastructureFilters = ({
filter !== env.type
? "opacity-60 border-b-2 border-b-transparent"
: "border-b-2 border-b-[#0079C2]"
} flex gap-2 font-medium text-sm px-[2px] py-2 transition-all duration-300 ease-in-out`}
} flex gap-2 font-medium 2xl:text-sm xl:text-xs px-[2px] py-2 transition-all duration-300 ease-in-out`}
>
{env.icon}
<div>{env.label}</div>
</button>
))}
</div>
<div className="flex flex-col gap-2 border-b border-[#9595A2] pb-8">
<h3 className="text-[18px] mb-5">Транспорт:</h3>
<div className="flex flex-col gap-2 border-b border-[#9595A2] 2xl:pb-8 pb-5">
<h3 className="text-[18px] 2xl:mb-5 mb-3">Транспорт:</h3>
{transports.map((trans) => (
<button
data-set={trans.type}
+5 -2
View File
@@ -1,14 +1,17 @@
import { isMobile } from "react-device-detect";
import { Mark } from "../types/Mark";
import MarkEducationIcon from "./icons/marks/MarkEducationIcon";
import MarkFoodIcon from "./icons/marks/MarkFoodIcon";
import MarkHeathyIcon from "./icons/marks/MarkHeathyIcon";
import MarkShopIcon from "./icons/marks/MarkShopIcon";
import { MarkSportIcon } from "./icons/marks/MarkSportIcon";
const markIcons: { [key: string]: React.ReactNode } = {
shop: <MarkShopIcon />,
food: <MarkFoodIcon />,
heathy: <MarkHeathyIcon />,
education: <MarkEducationIcon />,
sport: <MarkSportIcon />,
};
interface MarksContainerProps {
@@ -21,8 +24,8 @@ interface MarksContainerProps {
function MarksContainer({
marks,
filteredMarks,
markWidth = 52,
markHeigth = 52,
markWidth = isMobile ? 64 : 48,
markHeigth = isMobile ? 64 : 48,
}: MarksContainerProps) {
return (
<svg
+35 -62
View File
@@ -1,12 +1,9 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react";
import gsap from "gsap";
// import gsap from "gsap";
import { isMobile } from "react-device-detect";
import Button from "./Button";
import { Transition } from "react-transition-group";
import PointButton from "./PointButton";
import WalkIcon from "./icons/WalkIcon";
import MarksContainer from "./MarksContainer";
// import Button from "./Button";
// import { Transition } from "react-transition-group";
interface SequenceSliderProps {
path: string;
@@ -20,39 +17,39 @@ function SequenceSlider({ path }: SequenceSliderProps) {
const [touchPositionX, setTouchPositionX] = useState<number>();
const [loadedImages, setLoadedImages] = useState<number>(0);
function animate() {
const obj = { selectedImageIndex };
// function animate() {
// const obj = { selectedImageIndex };
function getDirection() {
const targetFrame =
obj.selectedImageIndex < arrayLength / 2 ? "left" : "right";
// function getDirection() {
// const targetFrame =
// obj.selectedImageIndex < arrayLength / 2 ? "left" : "right";
return targetFrame;
}
// return targetFrame;
// }
function getDuration() {
const direction = getDirection();
let duration;
// function getDuration() {
// const direction = getDirection();
// let duration;
if (direction === "left") {
duration = selectedImageIndex / 90;
} else {
duration = (arrayLength - selectedImageIndex) / 90;
}
// if (direction === "left") {
// duration = selectedImageIndex / 90;
// } else {
// duration = (arrayLength - selectedImageIndex) / 90;
// }
return duration;
}
// return duration;
// }
gsap.to(obj, {
selectedImageIndex: getDirection() === "left" ? 0 : arrayLength,
duration: getDuration(),
ease: "power1.inOut",
onUpdate: () => {
console.log("data", obj.selectedImageIndex);
setSelectedImageIndex(Math.round(obj.selectedImageIndex));
},
});
}
// gsap.to(obj, {
// selectedImageIndex: getDirection() === "left" ? 0 : arrayLength,
// duration: getDuration(),
// ease: "power1.inOut",
// onUpdate: () => {
// console.log("data", obj.selectedImageIndex);
// setSelectedImageIndex(Math.round(obj.selectedImageIndex));
// },
// });
// }
useEffect(() => {
if (selectedImageIndex === 360) {
@@ -115,9 +112,9 @@ function SequenceSlider({ path }: SequenceSliderProps) {
}
}, [movementX]);
const [width, setWidth] = useState<number>();
const [, setWidth] = useState<number>();
// const [heigth, setHeigth] = useState<number>();
const [top, setTop] = useState<number>();
const [, setTop] = useState<number>();
function handleResize() {
setWidth(window.innerWidth);
@@ -144,31 +141,7 @@ function SequenceSlider({ path }: SequenceSliderProps) {
/>
))}
<div className="absolute w-full h-full">
<Transition in={selectedImageIndex === 0} timeout={150}>
{(state) => (
<div className={` transition-opacity ${state}`}>
<MarksContainer
marks={[{ id: "tower_1", icon: "tower", x: 200, y: 200 }]}
markWidth={128}
markHeigth={128}
/>
<MarksContainer
marks={[{ id: "tower_2", icon: "tower", x: 1800, y: 300 }]}
markWidth={128}
markHeigth={128}
/>
<MarksContainer
marks={[{ id: "dvor", icon: "walk", x: 1000, y: 1100 }]}
markWidth={128}
markHeigth={128}
/>
</div>
)}
</Transition>
</div>
<div className="absolute bottom-8 w-full z-10 flex justify-center">
{/* <div className="absolute bottom-8 w-full z-10 flex justify-center">
<Transition in={selectedImageIndex !== 0} timeout={150}>
{(state) => (
<div className={`transition-opacity ${state}`}>
@@ -176,10 +149,10 @@ function SequenceSlider({ path }: SequenceSliderProps) {
</div>
)}
</Transition>
</div>
</div> */}
<div
className="absolute top-0 left-0 w-full h-full"
className="absolute top-0 left-0 w-full h-full cursor-e-resize"
onMouseMove={handleMouseMove}
onTouchMove={handleTouchMove}
onTouchStart={handleTouchStart}
+43
View File
@@ -0,0 +1,43 @@
function ComplexIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={64}
height={64}
fill="none"
// {...props}
>
<rect
width={61.333}
height={61.333}
x={1.333}
y={1.333}
fill="#0079C2"
rx={30.667}
/>
<rect
width={61.333}
height={61.333}
x={1.333}
y={1.333}
stroke="#fff"
strokeWidth={2.667}
rx={30.667}
/>
<path
fill="#fff"
fillRule="evenodd"
d="m18.78 43.465 3.16-.368h7.697l3.16.368v.933l-3.16-.18H21.94l-3.16.18v-.933Zm1.856-3.073v1.469l-1.092.13v-1.393l1.092-.206Zm0-1.952v1.47l-1.092.205v-1.388l1.092-.287Zm0-1.951v1.469l-1.092.276v-1.398l1.092-.347Zm0-1.947v1.475l-1.092.347V34.97l1.092-.429Zm0-1.951v.905l-1.092.488v-.905l1.092-.488Zm0-1.952v.911l-1.092.542v-.9l1.092-.553Zm0-1.951v.91l-1.092.63v-.906l1.092-.634Zm0-1.946v1.192l-1.092.634v-1.122l1.092-.704Zm0-1.947v1.188l-1.092.704v-1.116l1.092-.776Zm0-1.957v1.198l-1.092.776v-1.123l1.092-.85ZM30.734 33.41v-.91l-1.092-.494h-3.155l.382-1.116h2.773l1.092.542v-.906l-1.092-.542H27.18l.382-1.122h2.08l1.092.629v-.905l-1.092-.635h-1.768l.256-.758h1.512l1.092.634v-1.21l-1.092-.704H28.55l.257-.753h.819l1.091.704v-1.23l-1.091-.775h-.388l.257-.754h.13l1.092.775v-1.198l-1.091-.85h-7.697l-1.091.85v1.214l1.091-.775h.131l.257.754h-.388l-1.091.775v1.203l1.091-.704h.819l.257.753h-1.092l-1.092.705v1.209l1.092-.634h1.512l.256.759h-1.768l-1.092.634v.905l1.092-.629h2.08l.382 1.122h-2.462l-1.092.543v.905l1.092-.542h2.773l.382 1.116h-3.155l-1.092.494v.91l1.092-.487h3.482l.383 1.122.382-1.122h3.466l1.108.498Zm0 2.532v-1.48l-1.092-.417h-7.696l-1.092.417v1.48l1.092-.347h7.696l1.092.347Zm0 1.968v-1.486l-1.092-.346h-7.696l-1.092.346v1.486l1.092-.277h7.696l1.092.277Zm0 1.962v-1.48l-1.092-.276h-7.696l-1.092.276v1.48l1.092-.206h7.696l1.092.206Zm0 1.963v-1.48l-1.092-.206h-7.696l-1.092.206v1.48l1.092-.13h7.696l1.092.13Zm.207-1.442v1.469l1.092.13v-1.393l-1.092-.206Zm0-1.952v1.47l1.092.205v-1.388l-1.092-.287Zm0-1.951v1.469l1.092.276v-1.398l-1.092-.347Zm0-1.947v1.475l1.092.347V34.97l-1.092-.429Zm0-1.951v.905l1.092.488v-.905l-1.092-.488Zm0-1.952v.911l1.092.542v-.9l-1.092-.553Zm0-1.951v.91l1.092.63v-.906l-1.092-.634Zm0-1.946v1.192l1.092.634v-1.122l-1.092-.704Zm0-1.947v1.188l1.092.704v-1.116l-1.092-.776Zm0-1.957v1.198l1.092.776v-1.123l-1.092-.85Zm0-3.724v3.253l1.092.845v-4.255l.202-.033v4.451l1.091.846v.482l-1.091-.845v1.11l1.091.776v.754l-1.091-.776v1.085l1.091.704v.76l-1.091-.706v1.112l1.091.629v.748l-1.091-.634v.905l1.091.629v.894l-1.091-.542v.916l1.091.542v.9l-1.091-.493v.905l1.091.483v.916l-1.091-.423v1.382l1.091.353v.482l-1.091-.352v1.388l1.091.276v.477l-1.091-.27v1.381l1.091.201v.483l-1.091-.201v1.382l1.091.13v.483l-3.711-.445h-7.697l-3.711.445v-.483l1.091-.13v-1.382l-1.091.2v-.498l1.091-.2V38.77l-1.091.27v-.476l1.091-.277v-1.387l-1.091.352v-.483l1.091-.352v-1.382l-1.091.422v-.9l1.091-.482v-.905l-1.091.493v-.9l1.091-.542v-.905l-1.091.542v-.884l1.091-.629v-.905l-1.091.635v-.76l1.091-.628v-1.112l-1.091.705v-.759l1.091-.704v-1.085l-1.091.776v-.792l1.091-.775V23.83l-1.091.845v-.482l1.091-.846v-4.45l.202.032v4.255l1.092-.845v-3.253l.202.033v3.052l1.092-.852h7.696l1.092.852V19.12l.267-.006ZM45.777 29.36h-2.085l.497-.33h1.588v.33Zm0 1.388h-4.181l.775-.515h3.406v.515Zm0 1.377h-6.255l.775-.543h5.458l.022.543ZM16.52 45.867l9.192-.542L47 46.002v.494H16.52v-.63Zm21.888-12.355v.624h7.369v.759h-7.369v.623h7.369v.764h-7.369v.619h7.369v.742h-7.369v1.084h7.369v.331h-7.369v1.057h7.369v.33h-7.369v1.085h7.369v.325h-7.369v1.057h7.369v.331h-7.369v.618h7.014v.765h-7.21l-1.354.065v-.673l1.36-.179v-.618l-1.36.185v-.342l1.36-.184v-1.063l-1.36.282v-.325l1.36-.282v-1.084l-1.36.38v-.326l1.36-.385V39.02l-1.36.483v-.331l1.36-.482v-1.047l-1.36.602v-.672l1.36-.672v-.619l-1.36.678v-.672l1.36-.77v-.623l-1.36.78v-.672l1.36-.867v-1.139h7.564v.542l-7.374-.027Zm-14.95-14.761h4.667v.542h-4.662l-.005-.542Z"
clipRule="evenodd"
/>
<path
fill="#fff"
fillRule="evenodd"
d="m26.362 32.363-.382 1.122h-.383l-.382-1.122h1.147Zm.671-2.038-.382 1.122h-1.747l-.382-1.122h2.511Zm.693-2.033-.382 1.122H24.19l-.382-1.122h3.92Zm.502-1.49-.256.758h-4.41l-.263-.759h4.93Zm.694-2.034-.257.754h-5.78l-.257-.754h6.294Zm-10.715-3.664 2.238-2.017-2.238-.336v2.353Zm15.12 1.794-3.712-3.1h-7.696l-3.712 3.1v-.482l3.712-3.101h7.696l3.712 3.1v.483Zm0-1.794-2.238-2.017 2.238-.336v2.353Zm-3.712 1.626-.257.759h-7.161l-.257-.759h7.675Zm-2.79 12.37h-2.117v.483h2.118v-.482Zm0 2.04h-2.117v.503h2.118v-.504Zm0 2.032h-2.117v.482h2.118v-.482Zm18.93-11.21h-7.543l-1.354 1.284v-.325l1.36-1.274h7.565l-.028.314Zm-7.565.894h6.223l-.492.325H38.19l-1.332 1.187v-.314l1.332-1.198Zm0 1.111h4.547l-.775.515H38.19l-1.36 1.084v-.542l1.36-1.057Zm0 1.892-1.36.976v-.515l1.36-.976h2.489l-.775.542-1.714-.027Zm0 1.382-1.332.89v-.516l1.36-.878-.028.504Zm0-7.746 3.597 1.014H38.19l-1.332 1.43v-.932l1.332-1.512Zm-11.364 15.72h-2.118v.483h2.118v-.482Z"
clipRule="evenodd"
/>
</svg>
);
}
export default ComplexIcon;
@@ -0,0 +1,28 @@
function InfrastructureIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={20}
height={20}
fill="none"
// {...props}
>
<g clipPath="url(#a)">
<path
stroke="#fff"
strokeLinecap="square"
strokeWidth={1.5}
d="M2 17.53h1m0 0h8m-8 0V4.5h5.75M11 17.53h5v-3.89h-5m0 3.89v-3.89m0-4.39v4.39M5.5 7.5h2M5.5 10.5h3M5.5 13.5h3M9.804 3.315A3.548 3.548 0 0 0 9.5 4.75c0 3.5 4 6.25 4 6.25s4-2.75 4-6.25c0-.492-.104-.98-.305-1.435a3.743 3.743 0 0 0-.867-1.217 4.027 4.027 0 0 0-1.297-.813 4.232 4.232 0 0 0-3.062 0 4.027 4.027 0 0 0-1.297.813 3.743 3.743 0 0 0-.868 1.217Z"
/>
<circle cx={13.5} cy={5} r={1.5} fill="#fff" />
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h20v20H0z" />
</clipPath>
</defs>
</svg>
);
}
export default InfrastructureIcon;
+20
View File
@@ -0,0 +1,20 @@
function ParkIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={20}
height={20}
fill="none"
// {...props}
>
<path
stroke="#fff"
strokeLinecap="square"
strokeWidth={1.5}
d="M10 19v-6.5m0 0L7.5 10m2.5 2.5v-2m0 0V5m0 5.5 2-2m-2.511 6.427a2.335 2.335 0 0 1-.415.392 3.5 3.5 0 0 1-4.942-4.826c.175-.249.149-.604-.096-.784l-.065-.047A3 3 0 0 1 6.037 4.92c.26-.032.485-.221.513-.482l.009-.077a3.5 3.5 0 0 1 5.755-1.988c.517.456.911 1.334 1.098 2.089.062.247.281.427.534.456a3 3 0 0 1 2.108 4.707l-.106.081c-.238.183-.26.531-.087.777a3.487 3.487 0 0 1 .626 1.716 3.5 3.5 0 0 1-5.561 3.12 2.336 2.336 0 0 1-.415-.393.676.676 0 0 0-1.022 0Z"
/>
</svg>
);
}
export default ParkIcon;
+27
View File
@@ -0,0 +1,27 @@
function StylobateIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={20}
height={20}
fill="none"
// {...props}
>
<path
stroke="#fff"
strokeLinecap="square"
strokeWidth={1.5}
d="M6 16.53H2V2l4 2v12.53Zm0 0h7.752m0-11.086L18 4.5v12.03h-4.248m0 0V12.5"
/>
<path
stroke="#fff"
strokeLinecap="square"
strokeWidth={1.5}
d="M8.266 7.083A3.27 3.27 0 0 0 8 8.375C8 11.525 11.5 14 11.5 14S15 11.525 15 8.375c0-.443-.09-.882-.266-1.292a3.37 3.37 0 0 0-.76-1.094 3.512 3.512 0 0 0-1.135-.732 3.613 3.613 0 0 0-2.678 0c-.425.17-.81.418-1.136.732a3.37 3.37 0 0 0-.759 1.094Z"
/>
<circle cx={11.5} cy={8.5} r={1.5} fill="#fff" />
</svg>
);
}
export default StylobateIcon;
@@ -0,0 +1,28 @@
const MarkSportIcon = () => {
return (
<svg
x={9.5}
y={9.5}
width="45"
height="45"
viewBox="0 0 45 45"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_177_12572)">
<path
d="M18.5222 26.4775L26.4772 18.5226M34.631 10.3688L36.6198 8.38002M8.37968 36.6201L10.3684 34.6314M18.5222 8.97656L24.8862 2.61267L42.3871 20.1136L36.0231 26.4775L18.5222 8.97656ZM2.61233 24.8865L8.97629 18.5226L26.4772 36.0235L20.1132 42.3874L2.61233 24.8865Z"
stroke="white"
stroke-width="2.8125"
stroke-linecap="square"
/>
</g>
<defs>
<clipPath id="clip0_177_12572">
<rect width="45" height="45" fill="white" />
</clipPath>
</defs>
</svg>
);
};
export { MarkSportIcon };
+11 -10
View File
@@ -1,7 +1,7 @@
[
{
"id": "Dvor_0",
"src": "/images/Dvor/Panoram_Dvor.0001.jpg",
"src": "/images/Dvor/Panoram_Dvor.0000.jpg",
"position": [-23.12, 0, -13.4],
"links": [
{ "toId": "Dvor_16", "label": "" },
@@ -121,8 +121,8 @@
"src": "/images/Dvor/Panoram_Dvor.0012.jpg",
"position": [-122.41, 0, -66.02],
"links": [
{ "toId": "Dvor_11", "label": "" },
{ "toId": "Dvor_13", "label": "" }
{ "toId": "Dvor_13", "label": "" },
{ "toId": "Hall_5", "label": "Лифты" }
]
},
{
@@ -180,13 +180,13 @@
{
"id": "Hall_0",
"icon": "Elevator",
"src": "/images/Hall/NKS_360_Hall00.jpg",
"src": "/images/Hall/NKS_360_Lobby_0.jpg",
"position": [-103.29, 0, -67.74],
"links": [{ "toId": "Hall_5", "label": "Лифты" }]
},
{
"id": "Hall_2",
"src": "/images/Hall/NKS_360_Hall02.jpg",
"src": "/images/Hall/NKS_360_Lobby_2.jpg",
"position": [-104.21, 0, -76.41],
"links": [
{ "toId": "Hall_4", "label": "Лифты" },
@@ -196,7 +196,7 @@
{
"id": "Hall_4",
"icon": "Elevator",
"src": "/images/Hall/NKS_360_Hall04.jpg",
"src": "/images/Hall/NKS_360_Lobby_4.jpg",
"position": [-109.93, 0, -74.76],
"links": [
{ "toId": "Hall_5", "label": "Лифты" },
@@ -206,16 +206,17 @@
{
"id": "Hall_5",
"icon": "Elevator",
"src": "/images/Hall/NKS_360_Hall05.jpg",
"src": "/images/Hall/NKS_360_Lobby_5.jpg",
"position": [-108.74, 0, -66.61],
"links": [
{ "toId": "Hall_0", "label": "Лифты" },
{ "toId": "Hall_4", "label": "Лифты" }
{ "toId": "Hall_4", "label": "Лифты" },
{ "toId": "Dvor_12", "label": "" }
]
},
{
"id": "Hall_1",
"src": "/images/Hall/NKS_360_Hall01.jpg",
"src": "/images/Hall/NKS_360_Lobby_1.jpg",
"position": [-6.51, 0, 26.3],
"links": [
{ "toId": "Hall_3", "label": "Лифты" },
@@ -225,7 +226,7 @@
{
"id": "Hall_3",
"icon": "Elevator",
"src": "/images/Hall/NKS_360_Hall03.jpg",
"src": "/images/Hall/NKS_360_Lobby_3.jpg",
"position": [7.94, 0, 23.95],
"links": [{ "toId": "Hall_1", "label": "Лобби" }]
}
+65
View File
@@ -0,0 +1,65 @@
[
{
"id": "Niz_Dvor_1",
"src": "/images/NizDvor/NKS_360_NizDvor01.jpg",
"position": [-135.4, 0, -62.6],
"links": [
{ "toId": "Niz_Dvor_6", "label": "" },
{ "toId": "Niz_Dvor_2", "label": "" }
]
},
{
"id": "Niz_Dvor_2",
"src": "/images/NizDvor/NKS_360_NizDvor02.jpg",
"position": [-46.7, 0, 7.7],
"links": [
{ "toId": "Niz_Dvor_1", "label": "" },
{ "toId": "Niz_Dvor_3", "label": "" }
]
},
{
"id": "Niz_Dvor_3",
"src": "/images/NizDvor/NKS_360_NizDvor03.jpg",
"position": [-0.8, 0, 54.2],
"links": [
{ "toId": "Niz_Dvor_2", "label": "" },
{ "toId": "Niz_Dvor_4", "label": "" }
]
},
{
"id": "Niz_Dvor_4",
"src": "/images/NizDvor/NKS_360_NizDvor04.jpg",
"position": [60.5, 0, 22.7],
"links": [
{ "toId": "Niz_Dvor_3", "label": "" },
{ "toId": "Niz_Dvor_5", "label": "" }
]
},
{
"id": "Niz_Dvor_5",
"src": "/images/NizDvor/NKS_360_NizDvor05.jpg",
"position": [3.3, 0, -24.9],
"links": [
{ "toId": "Niz_Dvor_4", "label": "" },
{ "toId": "Niz_Dvor_0", "label": "" }
]
},
{
"id": "Niz_Dvor_0",
"src": "/images/NizDvor/NKS_360_NizDvor00.jpg",
"position": [-61.9, 0, -76.4],
"links": [
{ "toId": "Niz_Dvor_5", "label": "" },
{ "toId": "Niz_Dvor_6", "label": "" }
]
},
{
"id": "Niz_Dvor_6",
"src": "/images/NizDvor/NKS_360_NizDvor06.jpg",
"position": [-119.7, 0, -121.6],
"links": [
{ "toId": "Niz_Dvor_0", "label": "" },
{ "toId": "Niz_Dvor_1", "label": "" }
]
}
]
+34
View File
@@ -29,3 +29,37 @@ body {
.exited {
opacity: 0;
}
::-webkit-scrollbar {
width: 2px;
height: 2px;
}
::-webkit-scrollbar-button {
width: 0px;
height: 0px;
}
::-webkit-scrollbar-thumb {
background: #e1e1e1;
border: 0px none #ffffff;
border-radius: 50px;
}
::-webkit-scrollbar-thumb:hover {
background: #ffffff;
}
::-webkit-scrollbar-thumb:active {
background: #000000;
}
::-webkit-scrollbar-track {
background: #666666;
border: 0px none #ffffff;
border-radius: 50px;
}
::-webkit-scrollbar-track:hover {
background: #666666;
}
::-webkit-scrollbar-track:active {
background: #333333;
}
::-webkit-scrollbar-corner {
background: transparent;
}
+5
View File
@@ -4,6 +4,7 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";
import VirtualTourPage from "./pages/VirtualTourPage.tsx";
import MainPage from "./pages/MainPage.tsx";
import Infra2Page from "./pages/Infra2Page.tsx";
import VirtualTour2Page from "./pages/VirtualTour2Page.tsx";
const router = createBrowserRouter([
{
@@ -14,6 +15,10 @@ const router = createBrowserRouter([
path: "/virtual-tour",
element: <VirtualTourPage />,
},
{
path: "/virtual-tour-2",
element: <VirtualTour2Page />,
},
{
path: "/infra2",
element: <Infra2Page />,
+200
View File
@@ -350,5 +350,205 @@
"y": 1080,
"icon": "education",
"distance": 500
},
{
"id": "education_6",
"label": "Гимназия №9",
"x": 1620,
"y": 940,
"icon": "education",
"distance": 800
},
{
"id": "education_7",
"label": "УрФУ ИНЭУ",
"x": 1360,
"y": 1230,
"icon": "education",
"distance": 500
},
{
"id": "education_8",
"label": "Империя",
"x": 1320,
"y": 1280,
"icon": "education",
"distance": 500
},
{
"id": "education_9",
"label": "Гимназия №2",
"x": 1080,
"y": 1350,
"icon": "education",
"distance": 400
},
{
"id": "education_10",
"label": "Детский сад №472",
"x": 730,
"y": 1180,
"icon": "education",
"distance": 500
},
{
"id": "education_11",
"label": "Детский сад №251",
"x": 760,
"y": 1120,
"icon": "education",
"distance": 400
},
{
"id": "education_12",
"label": "Детский сад №252 Кораблик",
"x": 550,
"y": 1110,
"icon": "education",
"distance": 700
},
{
"id": "education_13",
"label": "Детский сад №414",
"x": 640,
"y": 1310,
"icon": "education",
"distance": 700
},
{
"id": "sport_1",
"label": "Clinch",
"x": 700,
"y": 1130,
"icon": "sport",
"distance": 500
},
{
"id": "sport_2",
"label": "Точка",
"x": 970,
"y": 1180,
"icon": "sport",
"distance": 250
},
{
"id": "sport_3",
"label": "Aversfit",
"x": 1160,
"y": 1220,
"icon": "sport",
"distance": 300
},
{
"id": "sport_4",
"label": "Локомотив-изумруд",
"x": 1260,
"y": 1320,
"icon": "sport",
"distance": 450
},
{
"id": "sport_5",
"label": "Powerhouse Gym",
"x": 1470,
"y": 1340,
"icon": "sport",
"distance": 700
},
{
"id": "sport_6",
"label": "Бассейн Дворца Молодежи",
"x": 1030,
"y": 1450,
"icon": "sport",
"distance": 550
},
{
"id": "sport_7",
"label": "Happy Gymnastic",
"x": 660,
"y": 1230,
"icon": "sport",
"distance": 600
},
{
"id": "sport_8",
"label": "Encore Fitness",
"x": 1100,
"y": 910,
"icon": "sport",
"distance": 250
},
{
"id": "sport_9",
"label": "Реформа",
"x": 1090,
"y": 790,
"icon": "sport",
"distance": 400
},
{
"id": "sport_10",
"label": "Topstretching",
"x": 1010,
"y": 820,
"icon": "sport",
"distance": 350
},
{
"id": "sport_11",
"label": "Динамо",
"x": 1410,
"y": 580,
"icon": "sport",
"distance": 850
},
{
"id": "sport_12",
"label": "ДИВС",
"x": 1050,
"y": 570,
"icon": "sport",
"distance": 650
},
{
"id": "sport_13",
"label": "New Fit",
"x": 1250,
"y": 990,
"icon": "sport",
"distance": 400
},
{
"id": "sport_14",
"label": "Облака",
"x": 1360,
"y": 1030,
"icon": "sport",
"distance": 450
},
{
"id": "sport_15",
"label": "Bright Fit",
"x": 1540,
"y": 1200,
"icon": "sport",
"distance": 700
},
{
"id": "sport_15",
"label": "Bright Fit",
"x": 1540,
"y": 1200,
"icon": "sport",
"distance": 700
},
{
"id": "sport_16",
"label": "Bright Fit",
"x": 1540,
"y": 1200,
"icon": "sport",
"distance": 700
}
]
+17 -6
View File
@@ -6,15 +6,18 @@ import DistanceCircle from "../components/DistanceCircle";
import Button from "../components/Button";
import InfrastructureFilters from "../components/InfrastructurePage/InfrastructureFilters";
import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
import CrossIcon from "../components/icons/CrossIcon";
// import CrossIcon from "../components/icons/CrossIcon";
import { useNavigate } from "react-router-dom";
import ComplexIcon from "../components/icons/ComplexIcon";
const marks = _marks as Mark[];
function Infra2Page() {
const [selectedRange, setSelectedRange] = useState<number>(800);
const [selectedRange, setSelectedRange] = useState<number>(850);
const [width, setWidth] = useState<number>();
const [top, setTop] = useState<number>();
const [filteredMarks, setFilteredMarks] = useState(marks);
const navigate = useNavigate();
function handleResize() {
setWidth(window.innerWidth);
@@ -44,11 +47,11 @@ function Infra2Page() {
<DistanceCircle selectedRange={selectedRange} />
</div>
<div className="absolute h-full top-0 left-0 z-[99999999] w-[260px] bg-[#002347] bg-opacity-90 select-none px-6 py-5 flex flex-col justify-between gap-8">
<div className="absolute h-screen overflow-y-auto top-0 left-0 z-[99999999] w-[260px] bg-[#002347] bg-opacity-90 select-none px-6 py-5 flex flex-col justify-between gap-8">
<div className="flex flex-col gap-3">
<div className="flex justify-end">
{/* <div className="flex justify-end">
<CrossIcon />
</div>
</div> */}
<InfrastructureFilters
setFilteredMarks={setFilteredMarks}
setSelectedRange={setSelectedRange}
@@ -56,7 +59,15 @@ function Infra2Page() {
selectedRange={selectedRange}
/>
</div>
<Button text="Генплан" icon={<ArrowLeftIcon />} widthFull />
<Button
text="Генплан"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate("/")}
/>
</div>
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center">
<ComplexIcon />
</div>
</div>
);
+27
View File
@@ -1,9 +1,36 @@
import { useNavigate } from "react-router-dom";
import Button from "../components/Button";
import SequenceSlider from "../components/SequenceSlider";
import InfrastructureIcon from "../components/icons/InfrastructureIcon";
import ParkIcon from "../components/icons/ParkIcon";
import StylobateIcon from "../components/icons/StylobateIcon";
function MainPage() {
const navigate = useNavigate();
return (
<div className="h-screen touch-none">
<SequenceSlider path="/images/seq" />
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-10">
<div className="flex gap-3">
<Button
text="Стилобат"
icon={<StylobateIcon />}
onClick={() => navigate("/virtual-tour")}
/>
<Button
text="Двор комплекса"
icon={<ParkIcon />}
onClick={() => navigate("/virtual-tour-2")}
/>
<Button
text="Инфраструктура"
icon={<InfrastructureIcon />}
onClick={() => navigate("/infra2")}
/>
</div>
</div>
</div>
);
}
+113
View File
@@ -0,0 +1,113 @@
import { Canvas } from "@react-three/fiber";
import { Html, OrbitControls } from "@react-three/drei";
import { Suspense, useRef, useState } from "react";
import { OrbitControls as OrbitControlsImpl } from "three-stdlib";
import { useFullscreen } from "ahooks";
import SphereTour from "../components/SphereTour";
import PointButton from "../components/PointButton";
import WalkIcon from "../components/icons/WalkIcon";
import Button from "../components/Button";
import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
import FullscreenIcon from "../components/icons/FullscreenIcon";
import WindowModeIcon from "../components/icons/WindowModeIcon";
import _images from "../images2.json";
import Image from "../types/Image";
import ElevatorIcon from "../components/icons/ElevatorIcon";
import Loader from "../components/Loader";
import { useNavigate } from "react-router-dom";
import { isIOS } from "react-device-detect";
const images = _images as Image[];
function VirtualTour2Page() {
const [selectedImageId, setSelectedImageId] = useState<string>(images[0].id);
const orbitRef = useRef<OrbitControlsImpl>(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
function handleSelectImageId(toId: string) {
setSelectedImageId(toId);
console.log(toId);
}
return (
<div ref={fullscreenRef} className="h-screen bg-black">
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-[99999999]">
<Button
text="Генплан"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate("/")}
/>
</div>
{!isIOS && (
<div className="absolute xl:top-8 top-4 xl:right-8 right-4 z-[99999999] select-none">
<Button
text="Во весь экран"
icon={isFullscreen ? <WindowModeIcon /> : <FullscreenIcon />}
onClick={toggleFullscreen}
/>
</div>
)}
<Canvas camera={{ fov: 65 }}>
<Suspense fallback={<Loader />}>
<ambientLight intensity={2.5} />
{images.map((image) => (
<>
{/* <SphereTour key={index} src={image.src} position={image.position} /> */}
{image.id === selectedImageId &&
image.links?.map((link, index) => (
<Html
key={index}
position={
images.find((image) => image.id === link.toId)?.position
}
center
>
<PointButton
icon={
images.find((image) => image.id === link.toId)?.icon ===
"Elevator" ? (
<ElevatorIcon />
) : (
<WalkIcon />
)
}
label={link.label}
onClick={() => handleSelectImageId(link.toId)}
/>
</Html>
))}
</>
))}
{images.map((image) => (
<SphereTour
src={image.src}
position={image.position}
opacity={Number(image.id === selectedImageId)}
/>
))}
<OrbitControls
ref={orbitRef}
maxDistance={0.001}
enableZoom={false}
rotateSpeed={0.5}
reverseOrbit
target={
images.find((image) => image.id === selectedImageId)?.position
}
/>
</Suspense>
</Canvas>
</div>
);
}
export default VirtualTour2Page;
+19 -33
View File
@@ -14,6 +14,8 @@ import _images from "../images.json";
import Image from "../types/Image";
import ElevatorIcon from "../components/icons/ElevatorIcon";
import Loader from "../components/Loader";
import { useNavigate } from "react-router-dom";
import { isIOS } from "react-device-detect";
const images = _images as Image[];
@@ -22,6 +24,7 @@ function VirtualTourPage() {
const orbitRef = useRef<OrbitControlsImpl>(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
function handleSelectImageId(toId: string) {
setSelectedImageId(toId);
@@ -30,43 +33,26 @@ function VirtualTourPage() {
return (
<div ref={fullscreenRef} className="h-screen bg-black">
<div className="absolute h-full top-0 left-0 z-[99999999] w-[260px] bg-[#002347] bg-opacity-90 select-none p-8 flex flex-col justify-between gap-8">
<div className="flex flex-col gap-8">
{selectedImageId.includes("Dvor") && (
<>
<h2 className="font-tenor text-2xl">
Внутренний
<br />
двор
</h2>
<img src="/images/maps/Stilobat.svg" alt="" />
</>
)}
{selectedImageId.includes("Lobby_1") && (
<>
<h2 className="font-tenor text-2xl">Лобби</h2>
<img src="/images/maps/Lobby.svg" alt="" />
</>
)}
{selectedImageId.includes("Lobby_2") && (
<>
<h2 className="font-tenor text-2xl">Лобби</h2>
<img src="/images/maps/Lobby.svg" alt="" />
</>
)}
</div>
<Button text="Генплан" icon={<ArrowLeftIcon />} widthFull />
</div>
<div className="absolute top-0 right-0 z-[99999999] px-10 py-6 select-none">
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-[99999999]">
<Button
text="Во весь экран"
icon={isFullscreen ? <WindowModeIcon /> : <FullscreenIcon />}
onClick={toggleFullscreen}
text="Генплан"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate("/")}
/>
</div>
<Canvas>
{!isIOS && (
<div className="absolute xl:top-8 top-4 xl:right-8 right-4 z-[99999999] select-none">
<Button
text="Во весь экран"
icon={isFullscreen ? <WindowModeIcon /> : <FullscreenIcon />}
onClick={toggleFullscreen}
/>
</div>
)}
<Canvas camera={{ fov: 65 }}>
<Suspense fallback={<Loader />}>
<ambientLight intensity={2.5} />