This commit is contained in:
2024-05-03 18:44:16 +05:00
parent 9725d59c1b
commit 7ab4e7fb75
98 changed files with 7641 additions and 533 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 MiB

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 MiB

After

Width:  |  Height:  |  Size: 944 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 MiB

After

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 KiB

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 KiB

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.
-2
View File
@@ -16,8 +16,6 @@ function PointButton({ icon, label, onClick }: PointButtonProps) {
{label}
</div>
)}
{/* <div className="absolute h-20 w-0.5 bg-white top-[100%]"></div> */}
{/* <div className="absolute top-[120px] w-1.5 h-1.5 bg-white rounded-full"></div> */}
</button>
);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -6,7 +6,7 @@ interface Props {
onMouseLeave?: () => void;
}
function MarkApartArea1({ x, y, onClick, onMouseEnter, onMouseLeave }: Props) {
function MarkApartArea2({ x, y, onClick, onMouseEnter, onMouseLeave }: Props) {
return (
<svg
x={x}
@@ -82,4 +82,4 @@ function MarkApartArea1({ x, y, onClick, onMouseEnter, onMouseLeave }: Props) {
);
}
export default MarkApartArea1;
export default MarkApartArea2;
@@ -1,7 +0,0 @@
import React from "react";
function Floor23() {
return <div>Floor23</div>;
}
export default Floor23;
@@ -1,7 +0,0 @@
import React from "react";
function Floor24() {
return <div>Floor24</div>;
}
export default Floor24;
@@ -1,7 +0,0 @@
import React from "react";
function Floor25() {
return <div>Floor25</div>;
}
export default Floor25;
@@ -1,54 +0,0 @@
interface Props {
x: number;
y: number;
onClick: () => void;
}
function Floor26({ x, y, onClick }: Props) {
return (
<svg
x={x}
y={y}
onClick={onClick}
xmlns="http://www.w3.org/2000/svg"
width={464}
height={80}
data-name="\u0421\u043B\u043E\u0439 2"
className="group cursor-pointer"
>
<g>
<path
d="M1 24c36.33 14.33 72.67 28.67 109 43 97.67 4.33 195.33 8.67 293 13 .67-9.33 1.33-18.67 2-28L109 37C72.67 24.67 36.33 12.33 0 0c.33 8 .67 16 1 24Z"
style={{
opacity: 0.5,
}}
className="fill-transparent group-hover:fill-[#0079c2] transition-all duration-300"
/>
<rect
width={52}
height={18}
x={412}
y={58}
rx={4}
ry={4}
style={{
fill: "#002347",
}}
/>
<text
style={{
fill: "#fff",
fontFamily: "Inter",
fontSize: 10,
}}
transform="translate(416.68 71.2)"
>
<tspan x={0} y={0}>
{"26 этаж"}
</tspan>
</text>
</g>
</svg>
);
}
export default Floor26;
@@ -1,54 +0,0 @@
interface Props {
x: number;
y: number;
onClick: () => void;
}
function Floor27({ x, y, onClick }: Props) {
return (
<svg
x={x}
y={y}
onClick={onClick}
xmlns="http://www.w3.org/2000/svg"
width={468}
height={76}
className="group cursor-pointer"
>
<path
d="M2 24c36.33 12.33 72.67 24.67 109 37l296 15c.67-11.67 1.33-23.33 2-35-99.67-3.33-199.33-6.67-299-10C73.33 20.67 36.67 10.33 0 0c.67 8 1.33 16 2 24Z"
data-name={27}
style={{
opacity: 0.5,
}}
className="fill-transparent group-hover:fill-[#0079c2] transition-all duration-300"
/>
<rect
width={52}
height={18}
x={416}
y={51}
rx={4}
ry={4}
style={{
fill: "#002347",
strokeWidth: 0,
}}
/>
<text
style={{
fill: "#fff",
fontFamily: "Inter",
fontSize: 10,
}}
transform="translate(420.68 64.2)"
>
<tspan x={0} y={0}>
{"27 этаж"}
</tspan>
</text>
</svg>
);
}
export default Floor27;
@@ -1,53 +0,0 @@
interface Props {
x: number;
y: number;
onClick: () => void;
}
function Floor28({ x, y, onClick }: Props) {
return (
<svg
x={x}
y={y}
onClick={onClick}
xmlns="http://www.w3.org/2000/svg"
width={472.19}
height={73.29}
className="group cursor-pointer"
>
<path
d="M3.09 31.26c36.67 10.33 73.33 20.67 110 31 99.33 3.33 198.67 6.67 298 10 .67-13 1.33-26 2-39-100-2.67-200-5.33-300-8-37.34-8-74.67-16-112-24 .67 10 1.33 20 2 30Z"
style={{
opacity: 0.5,
}}
className="fill-transparent group-hover:fill-[#0079c2] transition-all duration-300"
/>
<rect
width={52}
height={18}
x={420.19}
y={45.6}
rx={4}
ry={4}
style={{
fill: "#002347",
strokeWidth: 0,
}}
/>
<text
style={{
fill: "#fff",
fontFamily: "Inter",
fontSize: 10,
}}
transform="translate(426 58)"
>
<tspan x={0} y={0}>
{"28 этаж"}
</tspan>
</text>
</svg>
);
}
export default Floor28;
+5 -6
View File
@@ -1,15 +1,15 @@
interface Point {
id: string;
id: string | number;
mapPosition: [number, number];
}
interface DvorMapProps {
interface Props {
points: Point[];
selectedPointId?: string;
onClick: (pointId: string) => void;
selectedPointId?: string | number;
onClick: (pointId: string | number) => void;
}
function DvorMap({ points, selectedPointId, onClick }: DvorMapProps) {
function DvorMap({ points, selectedPointId, onClick }: Props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -175,7 +175,6 @@ function DvorMap({ points, selectedPointId, onClick }: DvorMapProps) {
<g>
{points.map((point) => (
<circle
id={point.id}
cx={point.mapPosition[0]}
cy={point.mapPosition[1]}
r={4}
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -1,12 +1,12 @@
interface Point {
id: string;
id: string | number;
mapPosition: [number, number];
}
interface DvorMapProps {
points: Point[];
selectedPointId?: string;
onClick: (pointId: string) => void;
selectedPointId?: string | number;
onClick: (pointId: string | number) => void;
}
function OuterDvorMap({ points, selectedPointId, onClick }: DvorMapProps) {
@@ -34,7 +34,6 @@ function OuterDvorMap({ points, selectedPointId, onClick }: DvorMapProps) {
<g>
{points.map((point) => (
<circle
id={point.id}
cx={point.mapPosition[0]}
cy={point.mapPosition[1]}
r={4}
+17
View File
@@ -0,0 +1,17 @@
interface Point {
id: string | number;
mapPosition: [number, number];
mapLabel?: string;
}
interface Props {
points: Point[];
selectedPointId?: string | number;
onClick: (pointId: string | number) => void;
}
function RHataMap({ points, selectedPointId, onClick }: Props) {
return <div>RHataMap</div>;
}
export default RHataMap;
+71 -43
View File
@@ -1,140 +1,168 @@
[
{
"id": "R_Hata_0",
"id": 0,
"src": "/images/R_Hata/0.jpg",
"position": [62.6, 0, 61.3],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 9 }]
},
{
"id": "R_Hata_1",
"id": 1,
"src": "/images/R_Hata/1.jpg",
"position": [97.6, 0, 31.6],
"links": []
"mapPosition": [0, 0],
"links": [
{ "toId": 9 },
{ "toId": 8 },
{ "toId": 12 },
{ "toId": 6 },
{ "toId": 10 }
]
},
{
"id": "R_Hata_2",
"id": 2,
"src": "/images/R_Hata/2.jpg",
"position": [68.4, 0, 10.5],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 8 }, { "toId": 3 }]
},
{
"id": "R_Hata_3",
"id": 3,
"src": "/images/R_Hata/3.jpg",
"position": [58.3, 0, 5.9],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 2 }, { "toId": 5 }]
},
{
"id": "R_Hata_4",
"id": 4,
"src": "/images/R_Hata/4.jpg",
"position": [133.1, 0, 30.8],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 6 }, { "toId": 13 }]
},
{
"id": "R_Hata_5",
"id": 5,
"src": "/images/R_Hata/5.jpg",
"position": [48.6, 0, -22.1],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 3 }]
},
{
"id": "R_Hata_6",
"id": 6,
"src": "/images/R_Hata/6.jpg",
"position": [115.1, 0, 28.1],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 1 }, { "toId": 10 }, { "toId": 12 }, { "toId": 4 }]
},
{
"id": "R_Hata_7",
"id": 7,
"src": "/images/R_Hata/7.jpg",
"position": [57.2, 0, 41],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 8 }]
},
{
"id": "R_Hata_8",
"id": 8,
"src": "/images/R_Hata/8.jpg",
"position": [74.9, 0, 30.5],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 1 }, { "toId": 7 }, { "toId": 2 }]
},
{
"id": "R_Hata_9",
"id": 9,
"src": "/images/R_Hata/9.jpg",
"position": [84.3, 0, 50.6],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 0 }, { "toId": 1 }]
},
{
"id": "R_Hata_10",
"id": 10,
"src": "/images/R_Hata/10.jpg",
"position": [111, 0, 42.2],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 11 }, { "toId": 1 }, { "toId": 6 }]
},
{
"id": "R_Hata_11",
"id": 11,
"src": "/images/R_Hata/11.jpg",
"position": [117.9, 0, 57.1],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 10 }]
},
{
"id": "R_Hata_12",
"id": 12,
"src": "/images/R_Hata/12.jpg",
"position": [103.9, 0, 11.5],
"links": []
"links": [{ "toId": 6 }, { "toId": 1 }, { "toId": 15 }]
},
{
"id": "R_Hata_13",
"id": 13,
"src": "/images/R_Hata/13.jpg",
"position": [149.7, 0, 38.3],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 4 }, { "toId": 14 }]
},
{
"id": "R_Hata_14",
"id": 14,
"src": "/images/R_Hata/14.jpg",
"position": [156.4, 0, 21],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 13 }]
},
{
"id": "R_Hata_15",
"id": 15,
"src": "/images/R_Hata/15.jpg",
"position": [89.4, 0, -2.5],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 12 }, { "toId": 16 }]
},
{
"id": "R_Hata_16",
"id": 16,
"src": "/images/R_Hata/16.jpg",
"position": [85.6, 0, -22.1],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 15 }, { "toId": 17 }]
},
{
"id": "R_Hata_17",
"id": 17,
"src": "/images/R_Hata/17.jpg",
"position": [106.4, 0, -26.3],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 16 }, { "toId": 18 }]
},
{
"id": "R_Hata_18",
"id": 18,
"src": "/images/R_Hata/18.jpg",
"position": [127.3, 0, -30.2],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 17 }, { "toId": 19 }]
},
{
"id": "R_Hata_19",
"id": 19,
"src": "/images/R_Hata/19.jpg",
"position": [138.9, 0, -16.2],
"links": []
"mapPosition": [0, 0],
"links": [{ "toId": 18 }]
},
{
"id": "R_Hata_20",
"id": 20,
"src": "/images/R_Hata/20.jpg",
"position": [118.1, 0, -10.2],
"mapPosition": [0, 0],
"links": []
},
{
"id": "R_Hata_21",
"id": 21,
"src": "/images/R_Hata/21.jpg",
"position": [124.5, 0, 7.5],
"mapPosition": [0, 0],
"links": []
},
{
"id": "R_Hata_22",
"id": 22,
"src": "/images/R_Hata/22.jpg",
"position": [143.2, 0, 0.9],
"mapPosition": [0, 0],
"links": []
}
]
+169 -79
View File
@@ -1,111 +1,201 @@
[
{
"id": "L_Hata_0",
"src": "/images/L_Hata/L_Hata_0.webp",
"position": [-103.69, 0, -44.75],
"links": [{ "toId": "L_Hata_9", "label": "Коридор" }]
"id": 0,
"src": "/images/L_Hata/0.jpg",
"position": [-949.8, 0, -455],
"mapPosition": [-4.4, 269.3],
"links": [{ "toId": 9 }]
},
{
"id": "L_Hata_1",
"src": "/images/L_Hata/L_Hata_1.webp",
"position": [-100.25, 0, -42.89],
"id": 1,
"src": "/images/L_Hata/1.jpg",
"position": [-986.7, 0, -441.8],
"mapPosition": [61.6, 257],
"links": [{ "toId": 2 }, { "toId": 9 }]
},
{
"id": 2,
"src": "/images/L_Hata/2.jpg",
"position": [-1003.8, 0, -431.1],
"mapPosition": [93.5, 243.2],
"mapLabel": "Коридор",
"links": [
{ "toId": "L_Hata_9", "label": "Коридор" },
{ "toId": "L_Hata_8", "label": "Санузел" },
{ "toId": "L_Hata_7", "label": "Комната" },
{ "toId": "L_Hata_2", "label": "Коридор" },
{ "toId": "L_Hata_6", "label": "Комната" },
{ "toId": "L_Hata_11", "label": "Комната" }
{ "toId": 11 },
{ "toId": 13 },
{ "toId": 10 },
{ "toId": 1 },
{ "toId": 8 },
{ "toId": 4 },
{ "toId": 3 }
]
},
{
"id": "L_Hata_2",
"src": "/images/L_Hata/L_Hata_2.webp",
"position": [-98.79, 0, -40.85],
"links": [
{ "toId": "L_Hata_1", "label": "Коридор" },
{ "toId": "L_Hata_3", "label": "Кухня" }
]
"id": 3,
"src": "/images/L_Hata/3.jpg",
"position": [-986.4, 0, -421.6],
"mapPosition": [67.2, 221.7],
"links": [{ "toId": 2 }, { "toId": 7 }]
},
{
"id": "L_Hata_3",
"src": "/images/L_Hata/L_Hata_3.webp",
"position": [-95.06, 0, -38.66],
"links": [
{ "toId": "L_Hata_2", "label": "Коридор" },
{ "toId": "L_Hata_4", "label": "Кухня" }
]
"id": 4,
"src": "/images/L_Hata/4.jpg",
"position": [-993.1, 0, -413.9],
"mapPosition": [80.5, 210.3],
"links": [{ "toId": 2 }, { "toId": 6 }]
},
{
"id": "L_Hata_4",
"src": "/images/L_Hata/L_Hata_4.webp",
"position": [-95.07, 0, -35.38],
"links": [
{ "toId": "L_Hata_3", "label": "Кухня" },
{ "toId": "L_Hata_5", "label": "Балкон" }
]
"id": 5,
"src": "/images/L_Hata/5.jpg",
"position": [-959.7, 0, -391.5],
"mapPosition": [30.7, 162.2],
"links": [{ "toId": 6 }, { "toId": 15 }]
},
{
"id": "L_Hata_5",
"src": "/images/L_Hata/L_Hata_5.webp",
"position": [-92.78, 0, -31.67],
"links": [{ "toId": "L_Hata_4", "label": "Комната" }]
"id": 6,
"src": "/images/L_Hata/6.jpg",
"position": [-977.2, 0, -401.5],
"mapPosition": [57.3, 184.7],
"links": [{ "toId": 5 }, { "toId": 4 }]
},
{
"id": "L_Hata_6",
"src": "/images/L_Hata/L_Hata_6.webp",
"position": [-95.91, 0, -42],
"links": [{ "toId": "L_Hata_1", "label": "Коридор" }]
"id": 7,
"src": "/images/L_Hata/7.jpg",
"position": [-966.3, 0, -421.8],
"mapPosition": [33.4, 216.5],
"mapLabel": "Спальня",
"links": [{ "toId": 3 }, { "toId": 14 }]
},
{
"id": "L_Hata_7",
"src": "/images/L_Hata/L_Hata_7.webp",
"position": [-97.47, 0, -44.71],
"links": [{ "toId": "L_Hata_1", "label": "Коридор" }]
"id": 8,
"src": "/images/L_Hata/8.jpg",
"position": [-1011.5, 0, -412.3],
"mapPosition": [110.8, 212.8],
"links": [{ "toId": 2 }, { "toId": 22 }]
},
{
"id": "L_Hata_8",
"src": "/images/L_Hata/L_Hata_8.webp",
"position": [-100.68, 0, -45.16],
"links": [{ "toId": "L_Hata_1", "label": "Коридор" }]
"id": 9,
"src": "/images/L_Hata/9.jpg",
"position": [-966.6, 0, -443.7],
"mapPosition": [26.2, 253.8],
"mapLabel": "Спальня",
"links": [{ "toId": 1 }, { "toId": 0 }]
},
{
"id": "L_Hata_9",
"src": "/images/L_Hata/L_Hata_9.webp",
"position": [-102.13, 0, -43.45],
"links": [
{ "toId": "L_Hata_0", "label": "Прихожая" },
{ "toId": "L_Hata_1", "label": "Коридор" }
]
"id": 10,
"src": "/images/L_Hata/10.jpg",
"position": [-1004.7, 0, -451.1],
"mapPosition": [89.2, 277.9],
"mapLabel": "Санузел",
"links": [{ "toId": 2 }]
},
{
"id": "L_Hata_10",
"src": "/images/L_Hata/L_Hata_10.webp",
"position": [-102.73, 0, -42.12],
"links": []
"id": 11,
"src": "/images/L_Hata/11.jpg",
"position": [-1025.2, 0, -439.3],
"mapPosition": [127.2, 263.3],
"links": [{ "toId": 12 }, { "toId": 2 }, { "toId": 13 }]
},
{
"id": "L_Hata_11",
"src": "/images/L_Hata/L_Hata_11.webp",
"position": [-101.47, 0, -39.36],
"links": [
{ "toId": "L_Hata_1", "label": "Коридор" },
{ "toId": "L_Hata_12", "label": "Комната" }
]
"id": 12,
"src": "/images/L_Hata/12.jpg",
"position": [-1044.1, 0, -454.4],
"mapPosition": [154.6, 295],
"links": [{ "toId": 11 }]
},
{
"id": "L_Hata_12",
"src": "/images/L_Hata/L_Hata_12.webp",
"position": [-101.25, 0, -36.96],
"links": [
{ "toId": "L_Hata_11", "label": "Комната" },
{ "toId": "L_Hata_13", "label": "Санузел" }
]
"id": 13,
"src": "/images/L_Hata/13.jpg",
"position": [-1027.7, 0, -422.2],
"mapPosition": [136.3, 234.7],
"links": [{ "toId": 11 }, { "toId": 2 }]
},
{
"id": "L_Hata_13",
"src": "/images/L_Hata/L_Hata_13.webp",
"position": [-98.86, 0, -37.99],
"links": [{ "toId": "L_Hata_12", "label": "Комната" }]
"id": 14,
"src": "/images/L_Hata/14.jpg",
"position": [-946.4, 0, -423.2],
"mapPosition": [-0.9, 213.3],
"links": [{ "toId": 7 }]
},
{
"id": 15,
"src": "/images/L_Hata/15.jpg",
"position": [-952.5, 0, -372.7],
"mapPosition": [23.8, 128],
"mapLabel": "Гостиная",
"links": [{ "toId": 5 }, { "toId": 19 }, { "toId": 16 }]
},
{
"id": 16,
"src": "/images/L_Hata/16.jpg",
"position": [-943.4, 0, -355.6],
"mapPosition": [13.5, 95.9],
"links": [{ "toId": 15 }, { "toId": 19 }, { "toId": 20 }, { "toId": 17 }]
},
{
"id": 17,
"src": "/images/L_Hata/17.jpg",
"position": [-933.1, 0, -339],
"mapPosition": [1, 64.3],
"links": [{ "toId": 16 }, { "toId": 20 }, { "toId": 18 }]
},
{
"id": 18,
"src": "/images/L_Hata/18.jpg",
"position": [-927.7, 0, -316.3],
"mapPosition": [-1.4, 23.7],
"mapLabel": "Лоджия",
"links": [{ "toId": 17 }]
},
{
"id": 19,
"src": "/images/L_Hata/19.jpg",
"position": [-963.6, 0, -355.8],
"mapPosition": [47.5, 101.9],
"links": [{ "toId": 15 }, { "toId": 16 }, { "toId": 21 }, { "toId": 20 }]
},
{
"id": 20,
"src": "/images/L_Hata/20.jpg",
"position": [-952.4, 0, -334.2],
"mapPosition": [34.9, 61.5],
"mapLabel": "Кухня",
"links": [{ "toId": 21 }, { "toId": 19 }, { "toId": 16 }, { "toId": 17 }]
},
{
"id": 21,
"src": "/images/L_Hata/21.jpg",
"position": [-977.9, 0, -342],
"mapPosition": [75.7, 82.1],
"links": [{ "toId": 19 }, { "toId": 20 }]
},
{
"id": 22,
"src": "/images/L_Hata/22.jpg",
"position": [-1016.7, 0, -391.4],
"mapPosition": [126.9, 178.4],
"mapLabel": "Спальня",
"links": [{ "toId": 8 }, { "toId": 23 }]
},
{
"id": 23,
"src": "/images/L_Hata/23.jpg",
"position": [-1015, 0, -369.6],
"mapPosition": [130.2, 140.4],
"links": [{ "toId": 22 }, { "toId": 24 }]
},
{
"id": 24,
"src": "/images/L_Hata/24.jpg",
"position": [-994.2, 0, -373],
"mapPosition": [94.2, 140.3],
"links": [{ "toId": 23 }, { "toId": 25 }]
},
{
"id": 25,
"src": "/images/L_Hata/25.jpg",
"position": [-985.6, 0, -384.3],
"mapPosition": [76.3, 157.3],
"mapLabel": "Санузел",
"links": [{ "toId": 24 }]
}
]
+15 -3
View File
@@ -1,12 +1,19 @@
import { useNavigate } from "react-router-dom";
import Button from "../components/Button";
import SequenceSlider from "../components/SequenceSlider";
import { useFullscreen } from "ahooks";
import InfrastructureIcon from "../components/icons/InfrastructureIcon";
import { useRef } from "react";
import FullscreenIcon from "../components/icons/FullscreenIcon";
import WindowModeIcon from "../components/icons/WindowModeIcon";
function MainPage() {
const fullscreenRef = useRef(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
return (
<div className="h-screen touch-none">
<div ref={fullscreenRef} className="h-screen touch-none select-none">
<SequenceSlider
path="/images/seq"
onChange={(selectedImageIndex) =>
@@ -14,13 +21,18 @@ function MainPage() {
}
/>
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-50">
<div className="absolute top-6 right-6 z-50">
<div className="flex gap-3">
<Button
text="Инфраструктура"
// icon={<InfrastructureIcon />}
icon={<InfrastructureIcon />}
onClick={() => navigate("/infra2")}
/>
<Button
text="Во весь экран"
icon={isFullscreen ? <WindowModeIcon /> : <FullscreenIcon />}
onClick={toggleFullscreen}
/>
</div>
</div>
</div>
+17
View File
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
import Button from "../components/Button";
import { Transition } from "react-transition-group";
import Tower1FloorPlan from "../components/Tower1FloorPlan";
function Tower1Page() {
const [width, setWidth] = useState<number>();
@@ -40,6 +41,22 @@ function Tower1Page() {
className={`absolute select-none pointer-events-none`}
onLoad={() => setIsLoaded(true)}
/>
<svg
width="1920"
height="1920"
viewBox="0 0 1920 1920"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<Tower1FloorPlan
x={730}
y={565}
// onClick={(floor) => console.log("floor", floor)}
onClick={() => navigate("select")}
/>
</svg>
</div>
</div>
+41 -21
View File
@@ -142,28 +142,48 @@ function Tower1SelectPage() {
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
{marks.map((mark) => {
switch (mark.type) {
case "lock":
return (
<MarkLockIcon x={mark.x as number} y={mark.y as number} />
);
case "apart":
return (
<MarkApartIcon
x={mark.x as number}
y={mark.y as number}
text={mark.text as string}
text2={mark.text2 as string}
onClick={() => navigate(mark.url!)}
/>
);
default:
break;
}
})}
<MarkApartArea1
x={1378}
y={798}
onClick={() => navigate("1")}
onMouseEnter={() => setSelectedArea(1)}
onMouseLeave={() => setSelectedArea(null)}
/>
<MarkLockIcon x={380} y={875} />
<MarkLockIcon x={585} y={855} />
<MarkLockIcon x={725} y={855} />
<MarkLockIcon x={1140} y={855} />
<MarkLockIcon x={1280} y={855} />
<MarkLockIcon x={585} y={1100} />
<MarkLockIcon x={800} y={1120} />
<MarkLockIcon x={1070} y={1120} />
<MarkLockIcon x={1280} y={1100} />
</svg>
<div
className={`w-[202px] h-[200px] bg-[#002347] absolute z-50 pointer-events-none p-5 flex flex-col gap-4 transition-opacity ${
selectedArea ? "opacity-100" : "opacity-0"
}`}
style={{
top: mousePos[1] + top - 200,
left: mousePos[0],
}}
>
<h2 className="font-tenor text-2xl leading-[26.4px]">
3-комнатные апартаменты
</h2>
<p className="flex gap-1 text-sm">
<span className="font-medium">Площадь</span>
<span className="text-[#9595A2]">116.8 м²</span>
</p>
<hr className="border-[#0079C2] opacity-40" />
<div className="flex flex-col">
<p className="text-[#9595A2] text-sm">Стоимость</p>
<p className="font-tenor text-xl">
{/* {(7500600).toLocaleString("ru")} руб. */}- руб.
</p>
</div>
</div>
</div>
<div className="absolute left-8 bottom-8 z-50">
<Button
+146 -59
View File
@@ -5,6 +5,7 @@ import Button from "../components/Button";
import { Transition } from "react-transition-group";
import MarkTower1ApartSelectIcon from "../components/icons/marks/MarkTower1ApartSelectIcon";
import MarkApartPoint from "../components/icons/marks/MarkApartPoint";
import LHataMap from "../components/maps/LHataMap";
function Tower2ApartLauout() {
const [width, setWidth] = useState<number>();
@@ -24,77 +25,163 @@ function Tower2ApartLauout() {
}, []);
return (
<>
<div className="scene absolute w-full h-full overflow-hidden">
<div
className="absolute left-0"
style={{
width: `${width}px`,
height: `${width}px`,
top: `-${top}px`,
}}
>
<img
width={`${width}px`}
height={`${width}px`}
src="/images/Tower2/ApartLayout.jpg"
alt=""
className={`absolute select-none pointer-events-none`}
onLoad={() => setIsLoaded(true)}
/>
<div className="scene absolute w-full h-full overflow-hidden">
<div className="absolute top-0 left-0 w-[260px] min-h-screen bg-[#002347] bg-opacity-90 z-[99999999] p-7 flex flex-col justify-between">
<div className="flex flex-col">
<h2 className="font-tenor text-2xl mb-4">3-комнатные апартаменты</h2>
<div className="flex flex-col mb-7">
<p>
<span className="font-medium">Башня</span>{" "}
<span className="text-[#9595A2]">1</span>
</p>
<p>
<span className="font-medium">Этаж</span>{" "}
<span className="text-[#9595A2]">7-28</span>
</p>
<p>
<span className="font-medium">Площадь</span>{" "}
<span className="text-[#9595A2]">116.8 м²</span>
</p>
</div>
<div className="self-center mb-7">
<LHataMap />
</div>
<div className="mb-7">
<p className="text-[#9595A2] text-sm leading-[18.2px]">
Стоимость:
</p>
<p className="font-tenor text-lg leading-[23.4px]">- руб.</p>
</div>
<div className="mb-7">
<p className="text-[#9595A2] text-sm leading-[18.2px]">Статус:</p>
<p className="font-tenor text-lg leading-[23.4px]">В продаже</p>
</div>
</div>
<svg
width="1920"
height="1920"
viewBox="0 0 1920 1920"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<MarkTower1ApartSelectIcon
x={486}
y={716}
onMouseEnter={function (): void {
throw new Error("Function not implemented.");
}}
onMouseLeave={function (): void {
throw new Error("Function not implemented.");
}}
/>
<MarkApartPoint x={550} y={800} text="Спальня" text2="13.1 м²" />
<MarkApartPoint x={705} y={790} text="Спальня" text2="14.2 м²" />
<MarkApartPoint x={970} y={785} text="Гостиная" text2="31.5 м²" />
<MarkApartPoint x={1100} y={805} text="Кухня" text2="31.5 м²" />
<MarkApartPoint x={1270} y={720} text="Лоджия" text2="4.0 м²" />
<MarkApartPoint x={515} y={985} text="Санузел" text2="5.2 м²" />
<MarkApartPoint x={645} y={995} text="Коридор" text2="15.0 м²" />
<MarkApartPoint x={870} y={980} text="Санузел" text2="5.8 м²" />
<MarkApartPoint x={790} y={1115} text="Спальня" text2="17.4 м²" />
</svg>
<div className="flex flex-col gap-2">
<Button
text="Начать 3D тур"
widthFull
onClick={() => navigate("/virtual-tour-4?id=2")}
/>
<Button
text="Этажный план"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate(-1)}
/>
</div>
</div>
<div className="absolute left-8 bottom-8 z-50">
<Button
text="Этажный план"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate(-1)}
<div
className="absolute left-0"
style={{
width: `${width}px`,
height: `${width}px`,
top: `-${top}px`,
}}
>
<img
width={`${width}px`}
height={`${width}px`}
src="/images/Tower2/ApartLayout.jpg"
alt=""
className={`absolute select-none pointer-events-none`}
onLoad={() => setIsLoaded(true)}
/>
<svg
width="1920"
height="1920"
viewBox="0 0 1920 1920"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<MarkTower1ApartSelectIcon
x={486}
y={716}
onMouseEnter={function (): void {
throw new Error("Function not implemented.");
}}
onMouseLeave={function (): void {
throw new Error("Function not implemented.");
}}
/>
<MarkApartPoint
x={550}
y={800}
text="Спальня"
text2="13.1 м²"
onClick={() => navigate("/virtual-tour-4?id=9")}
/>
<MarkApartPoint
x={705}
y={790}
text="Спальня"
text2="14.2 м²"
onClick={() => navigate("/virtual-tour-4?id=7")}
/>
<MarkApartPoint
x={970}
y={785}
text="Гостиная"
text2="31.5 м²"
onClick={() => navigate("/virtual-tour-4?id=15")}
/>
<MarkApartPoint
x={1100}
y={805}
text="Кухня"
text2="31.5 м²"
onClick={() => navigate("/virtual-tour-4?id=20")}
/>
<MarkApartPoint
x={1270}
y={720}
text="Лоджия"
text2="4.0 м²"
onClick={() => navigate("/virtual-tour-4?id=18")}
/>
<MarkApartPoint
x={515}
y={985}
text="Санузел"
text2="5.2 м²"
onClick={() => navigate("/virtual-tour-4?id=10")}
/>
<MarkApartPoint
x={645}
y={995}
text="Коридор"
text2="15.0 м²"
onClick={() => navigate("/virtual-tour-4?id=2")}
/>
<MarkApartPoint
x={870}
y={980}
text="Санузел"
text2="5.8 м²"
onClick={() => navigate("/virtual-tour-4?id=25")}
/>
<MarkApartPoint
x={790}
y={1115}
text="Спальня"
text2="17.4 м²"
onClick={() => navigate("/virtual-tour-4?id=22")}
/>
</svg>
</div>
<Transition in={!isLoaded} 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">
Загрузка...
</h2> */}
</div>
className={`absolute w-full h-full bg-black z-[99999999] transition-opacity duration-300 ${state}`}
></div>
)}
</Transition>
</>
</div>
);
}
+7 -17
View File
@@ -4,20 +4,7 @@ import { useEffect, useState } from "react";
import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
import Button from "../components/Button";
import { Transition } from "react-transition-group";
import Floor28 from "../components/icons/marks/Tower2/Floor28";
import Floor27 from "../components/icons/marks/Tower2/Floor27";
import Floor26 from "../components/icons/marks/Tower2/Floor26";
// const marks: Mark[] = [
// {
// id: "1",
// label: "Перейти к планировке",
// icon: "layout",
// x: 1000,
// y: 800,
// url: "/tower2/select",
// },
// ];
import Tower2FloorPlan from "../components/Tower2FloorPlan";
function Tower2Page() {
const [width, setWidth] = useState<number>();
@@ -64,9 +51,12 @@ function Tower2Page() {
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<Floor28 x={729} y={663} onClick={() => navigate("select")} />
<Floor27 x={730} y={693} onClick={() => navigate("select")} />
<Floor26 x={732} y={717} onClick={() => navigate("select")} />
<Tower2FloorPlan
x={747}
y={633}
// onClick={(floor) => console.log("floor", floor)}
onClick={() => navigate("select")}
/>
</svg>
</div>
</div>
+80 -82
View File
@@ -4,7 +4,7 @@ import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
import Button from "../components/Button";
import { Transition } from "react-transition-group";
import MarkLockIcon from "../components/icons/marks/MarkLockIcon";
import MarkApartArea1 from "../components/icons/marks/MarkApartArea1";
import MarkApartArea2 from "../components/icons/marks/MarkApartArea2";
function Tower2SelectPage() {
const [width, setWidth] = useState<number>(0);
@@ -38,97 +38,95 @@ function Tower2SelectPage() {
}
return (
<div>
<div className="scene absolute w-full h-full overflow-hidden">
<div className="scene absolute w-full h-full overflow-hidden">
<div
className="absolute left-0"
style={{
width: `${width}px`,
height: `${width}px`,
top: `-${top}px`,
}}
>
<img
width={`${width}px`}
height={`${width}px`}
src="/images/Split_LTower.jpg"
alt=""
className=""
onLoad={handleOnImageLoad}
/>
<svg
width="1920"
height="1920"
viewBox="0 0 1920 1920"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<MarkApartArea2
x={1378}
y={798}
onClick={() => navigate("1")}
onMouseEnter={() => setSelectedArea(1)}
onMouseLeave={() => setSelectedArea(null)}
/>
<MarkLockIcon x={380} y={875} />
<MarkLockIcon x={585} y={855} />
<MarkLockIcon x={725} y={855} />
<MarkLockIcon x={1140} y={855} />
<MarkLockIcon x={1280} y={855} />
<MarkLockIcon x={585} y={1100} />
<MarkLockIcon x={800} y={1120} />
<MarkLockIcon x={1070} y={1120} />
<MarkLockIcon x={1280} y={1100} />
</svg>
<div
className="absolute left-0"
className={`w-[202px] h-[200px] bg-[#002347] absolute z-50 pointer-events-none p-5 flex flex-col gap-4 transition-opacity ${
selectedArea ? "opacity-100" : "opacity-0"
}`}
style={{
width: `${width}px`,
height: `${width}px`,
top: `-${top}px`,
top: mousePos[1] + top - 200,
left: mousePos[0],
}}
>
<img
width={`${width}px`}
height={`${width}px`}
src="/images/Split_LTower.jpg"
alt=""
className=""
onLoad={handleOnImageLoad}
/>
<svg
width="1920"
height="1920"
viewBox="0 0 1920 1920"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-50 top-0 left-0 w-full h-full"
>
<MarkApartArea1
x={1378}
y={798}
onClick={() => navigate("1")}
onMouseEnter={() => setSelectedArea(1)}
onMouseLeave={() => setSelectedArea(null)}
/>
<MarkLockIcon x={380} y={875} />
<MarkLockIcon x={585} y={855} />
<MarkLockIcon x={725} y={855} />
<MarkLockIcon x={1140} y={855} />
<MarkLockIcon x={1280} y={855} />
<MarkLockIcon x={585} y={1100} />
<MarkLockIcon x={800} y={1120} />
<MarkLockIcon x={1070} y={1120} />
<MarkLockIcon x={1280} y={1100} />
</svg>
<div
className={`w-[202px] h-[200px] bg-[#002347] absolute z-50 pointer-events-none p-5 flex flex-col gap-4 transition-opacity ${
selectedArea ? "opacity-100" : "opacity-0"
}`}
style={{
top: mousePos[1] + top - 200,
left: mousePos[0],
}}
>
<h2 className="font-tenor text-2xl leading-[26.4px]">
2-комнатные апартаменты
</h2>
<p className="flex gap-1 text-sm">
<span className="font-medium">Площадь</span>
<span className="text-[#9595A2]">80 м²</span>
<h2 className="font-tenor text-2xl leading-[26.4px]">
3-комнатные апартаменты
</h2>
<p className="flex gap-1 text-sm">
<span className="font-medium">Площадь</span>
<span className="text-[#9595A2]">116.8 м²</span>
</p>
<hr className="border-[#0079C2] opacity-40" />
<div className="flex flex-col">
<p className="text-[#9595A2] text-sm">Стоимость</p>
<p className="font-tenor text-xl">
{/* {(7500600).toLocaleString("ru")} руб. */}- руб.
</p>
<hr className="border-[#0079C2] opacity-40" />
<div className="flex flex-col">
<p className="text-[#9595A2] text-sm">Стоимость</p>
<p className="font-tenor text-xl">
{(7500600).toLocaleString("ru")} руб.
</p>
</div>
</div>
</div>
<div className="absolute left-8 bottom-8 z-50">
<Button
text="Выбор этажа"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate(-1)}
/>
</div>
</div>
<div className="absolute left-8 bottom-8 z-50">
<Button
text="Выбор этажа"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate(-1)}
/>
</div>
<Transition in={!isLoaded} 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">
<Transition in={!isLoaded} 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">
Загрузка...
</h2> */}
</div>
)}
</Transition>
</div>
</div>
)}
</Transition>
</div>
);
}
+3 -3
View File
@@ -21,14 +21,14 @@ import OuterDvorMap from "../components/maps/OuterDvorMap";
const images = _images as Image[];
function VirtualTour2Page() {
const [selectedImageId, setSelectedImageId] = useState<string>(images[0].id);
const [selectedImageId, setSelectedImageId] = useState<string | number>(images[0].id);
const orbitRef = useRef<OrbitControlsImpl>(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
const [selectedPointId, setSelectedPointId] = useState<string>(images[0].id);
const [selectedPointId, setSelectedPointId] = useState<string | number>(selectedImageId);
function handleSelectImageId(toId: string) {
function handleSelectImageId(toId: string | number) {
setSelectedImageId(toId);
setSelectedPointId(toId);
console.log(toId);
+32 -10
View File
@@ -1,6 +1,6 @@
import { Canvas } from "@react-three/fiber";
import { Html, OrbitControls } from "@react-three/drei";
import { Suspense, useEffect, useRef, useState } from "react";
import { Suspense, useRef, useState } from "react";
import { OrbitControls as OrbitControlsImpl } from "three-stdlib";
import { useFullscreen } from "ahooks";
import SphereTour from "../components/SphereTour";
@@ -14,32 +14,54 @@ import _images from "../images3.json";
import Image from "../types/Image";
import ElevatorIcon from "../components/icons/ElevatorIcon";
import Loader from "../components/Loader";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { isIOS } from "react-device-detect";
import RHataMap from "../components/maps/RHataMap";
const images = _images as unknown as Image[];
function VirtualTour3Page() {
const [selectedImageId, setSelectedImageId] = useState<string>(images[19].id);
const { search } = useLocation();
const [selectedImageId, setSelectedImageId] = useState<string | number>(
Number(new URLSearchParams(search).get("id")) || 9
);
const orbitRef = useRef<OrbitControlsImpl>(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
const [selectedPointId, setSelectedPointId] = useState<string | number>(
selectedImageId
);
function handleSelectImageId(toId: string) {
function handleSelectImageId(toId: string | number) {
setSelectedImageId(toId);
setSelectedPointId(toId);
console.log(toId);
}
useEffect(() => {
setTimeout(() => {
orbitRef.current?.setAzimuthalAngle(-0.7);
}, 200);
}, [orbitRef]);
// useEffect(() => {
// setTimeout(() => {
// orbitRef.current?.setAzimuthalAngle(-0.7);
// }, 200);
// }, [orbitRef]);
return (
<div ref={fullscreenRef} className="h-screen bg-black select-none">
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-[99999999]">
<div className="absolute top-0 left-0 w-[260px] min-h-screen bg-[#002347] bg-opacity-90 z-[99999999] p-7 flex flex-col justify-between">
<div className="flex flex-col gap-9">
<h2 className="font-tenor text-2xl">2-комнатные апартаменты</h2>
<div className="self-center">
<RHataMap
points={images.map((image) => ({
id: image.id,
mapPosition: image.mapPosition,
}))}
selectedPointId={selectedPointId}
onClick={(pointId) => handleSelectImageId(pointId)}
/>
</div>
</div>
<Button
text="Генплан"
icon={<ArrowLeftIcon />}
+57 -16
View File
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Canvas } from "@react-three/fiber";
import { Html, OrbitControls } from "@react-three/drei";
import { Suspense, useEffect, useRef, useState } from "react";
import { Suspense, useRef, useState } from "react";
import { OrbitControls as OrbitControlsImpl } from "three-stdlib";
import { useFullscreen } from "ahooks";
import SphereTour from "../components/SphereTour";
@@ -14,38 +15,78 @@ import _images from "../images4.json";
import Image from "../types/Image";
import ElevatorIcon from "../components/icons/ElevatorIcon";
import Loader from "../components/Loader";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { isIOS } from "react-device-detect";
import LHataMap from "../components/maps/LHataMap";
const images = _images as Image[];
const images = _images as unknown as Image[];
function VirtualTour4Page() {
const [selectedImageId, setSelectedImageId] = useState<string>(images[0].id);
const { search } = useLocation();
const [selectedImageId, setSelectedImageId] = useState<string | number>(
Number(new URLSearchParams(search).get("id")) || 12
);
const orbitRef = useRef<OrbitControlsImpl>(null);
const canvasRef = useRef(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
const [selectedPointId, setSelectedPointId] = useState<string | number>(
selectedImageId
);
function handleSelectImageId(toId: string) {
function handleSelectImageId(toId: string | number) {
setSelectedImageId(toId);
setSelectedPointId(toId);
console.log(toId);
}
useEffect(() => {
setTimeout(() => {
orbitRef.current?.setAzimuthalAngle(-2.3);
}, 200);
}, [orbitRef]);
return (
<div ref={fullscreenRef} className="h-screen bg-black select-none">
<div className="absolute xl:left-8 left-4 xl:bottom-8 bottom-4 z-[99999999]">
<div className="absolute top-0 left-0 w-[260px] min-h-screen bg-[#002347] bg-opacity-90 z-[99999999] p-7 flex flex-col justify-between">
<div className="flex flex-col">
<h2 className="font-tenor text-2xl mb-4">3-комнатные апартаменты</h2>
<div className="flex flex-col mb-7">
<p>
<span className="font-medium">Башня</span>{" "}
<span className="text-[#9595A2]">1</span>
</p>
<p>
<span className="font-medium">Этаж</span>{" "}
<span className="text-[#9595A2]">7-28</span>
</p>
<p>
<span className="font-medium">Площадь</span>{" "}
<span className="text-[#9595A2]">116.8 м²</span>
</p>
</div>
<div className="self-center mb-7">
<LHataMap
points={images.map((image) => ({
id: image.id,
mapPosition: image.mapPosition,
mapLabel: image.mapLabel,
}))}
selectedPointId={selectedPointId}
onClick={(pointId) => handleSelectImageId(pointId)}
/>
</div>
<div className="mb-7">
<p className="text-[#9595A2] text-sm leading-[18.2px]">
Стоимость:
</p>
<p className="font-tenor text-lg leading-[23.4px]">- руб.</p>
</div>
<div className="mb-7">
<p className="text-[#9595A2] text-sm leading-[18.2px]">Статус:</p>
<p className="font-tenor text-lg leading-[23.4px]">В продаже</p>
</div>
</div>
<Button
text="Генплан"
text="Вид сверху"
icon={<ArrowLeftIcon />}
widthFull
onClick={() => navigate("/")}
onClick={() => navigate(-1)}
/>
</div>
@@ -59,7 +100,7 @@ function VirtualTour4Page() {
</div>
)}
<Canvas ref={canvasRef} camera={{ fov: 65 }}>
<Canvas camera={{ fov: 65 }}>
<Suspense fallback={<Loader />}>
<ambientLight intensity={2.5} />
+8 -3
View File
@@ -21,14 +21,18 @@ import DvorMap from "../components/maps/DvorMap";
const images = _images as Image[];
function VirtualTourPage() {
const [selectedImageId, setSelectedImageId] = useState<string>(images[0].id);
const [selectedImageId, setSelectedImageId] = useState<string | number>(
images[0].id
);
const orbitRef = useRef<OrbitControlsImpl>(null);
const fullscreenRef = useRef<HTMLDivElement>(null);
const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
const navigate = useNavigate();
const [selectedPointId, setSelectedPointId] = useState<string>(images[0].id);
const [selectedPointId, setSelectedPointId] = useState<string | number>(
selectedImageId
);
function handleSelectImageId(toId: string) {
function handleSelectImageId(toId: string | number) {
setSelectedImageId(toId);
setSelectedPointId(toId);
console.log(toId);
@@ -44,6 +48,7 @@ function VirtualTourPage() {
points={images.map((image) => ({
id: image.id,
mapPosition: image.mapPosition,
mapLabel: image.mapLabel,
}))}
selectedPointId={selectedPointId}
onClick={(pointId) => handleSelectImageId(pointId)}
+2 -1
View File
@@ -2,10 +2,11 @@ import { Vector3 } from "@react-three/fiber";
import Link from "./Link";
interface Image {
id: string;
id: string | number;
src: string;
position: Vector3;
mapPosition: [number, number];
mapLabel?: string;
icon?: string;
links?: Link[];
}