feat: float detail box
This commit is contained in:
parent
719a2eac00
commit
cfc19a42a2
|
|
@ -13,7 +13,6 @@ export function BuildingHeights({ area }: { area: any }) {
|
||||||
const appendAreas = useAreaStore((state) => state.appendAreas);
|
const appendAreas = useAreaStore((state) => state.appendAreas);
|
||||||
|
|
||||||
const requestBuildings = () => {
|
const requestBuildings = () => {
|
||||||
console.log(area);
|
|
||||||
const south = area[1].lat;
|
const south = area[1].lat;
|
||||||
const west = area[1].lng;
|
const west = area[1].lng;
|
||||||
const north = area[0].lat;
|
const north = area[0].lat;
|
||||||
|
|
@ -50,7 +49,29 @@ export function BuildingHeights({ area }: { area: any }) {
|
||||||
position: "relative",
|
position: "relative",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<button onClick={requestBuildings}>request</button>
|
<button
|
||||||
|
css={css({
|
||||||
|
color: "#ffffff",
|
||||||
|
|
||||||
|
backgroundColor: "#007bffe8",
|
||||||
|
backdropFilter: "blur(8px)",
|
||||||
|
border: "none",
|
||||||
|
padding: "0.5rem 1rem",
|
||||||
|
borderRadius: "8px",
|
||||||
|
outline: "#086ad4c2 solid 0.1rem",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "0.2s",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "0.5rem",
|
||||||
|
":hover": {
|
||||||
|
backgroundColor: "#085fbd",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
onClick={requestBuildings}
|
||||||
|
>
|
||||||
|
request
|
||||||
|
</button>
|
||||||
<ul
|
<ul
|
||||||
css={css({
|
css={css({
|
||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,76 @@
|
||||||
import React, { useRef, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from "@react-three/fiber";
|
||||||
import { useAreaStore } from "@/state/areaStore";
|
import { useAreaStore } from "@/state/areaStore";
|
||||||
import { OrbitControls } from "@react-three/drei";
|
import { OrbitControls, Html } from "@react-three/drei";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
function Building({
|
||||||
|
shape,
|
||||||
|
extrudeSettings,
|
||||||
|
tags,
|
||||||
|
}: {
|
||||||
|
shape: THREE.Shape;
|
||||||
|
extrudeSettings: any;
|
||||||
|
tags: any;
|
||||||
|
}) {
|
||||||
|
const [hovered, setHovered] = useState(false);
|
||||||
|
const [clicked, setClicked] = useState(false);
|
||||||
|
const [hoverPos, setHoverPos] = useState<THREE.Vector3 | null>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<mesh
|
||||||
|
onPointerOver={(e) => {
|
||||||
|
setHovered(true);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
onPointerOut={(e) => {
|
||||||
|
setHovered(false);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
onPointerMove={(e) => {
|
||||||
|
setHoverPos(e.point.clone());
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
setClicked(!clicked);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
rotation={[-Math.PI / 2, 0, 0]}
|
||||||
|
>
|
||||||
|
<extrudeGeometry args={[shape, extrudeSettings]} />
|
||||||
|
<meshStandardMaterial
|
||||||
|
color={hovered || clicked ? "#007bff" : "#9da0a3"}
|
||||||
|
/>
|
||||||
|
{(hovered || clicked) && hoverPos && (
|
||||||
|
<Html
|
||||||
|
position={[
|
||||||
|
hoverPos.x,
|
||||||
|
hoverPos.y + extrudeSettings.depth + 0.5,
|
||||||
|
hoverPos.z,
|
||||||
|
]}
|
||||||
|
center
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "#000000",
|
||||||
|
backgroundColor: "#ffffff96",
|
||||||
|
backdropFilter: "blur(8px)",
|
||||||
|
border: "none",
|
||||||
|
padding: "0.5rem 1rem",
|
||||||
|
borderRadius: "8px",
|
||||||
|
fontWeight: "300",
|
||||||
|
fontSize: "12px",
|
||||||
|
outline: "rgba(240, 240, 244, 0.51) solid 0.1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>{JSON.stringify(tags)}</div>
|
||||||
|
</div>
|
||||||
|
</Html>
|
||||||
|
)}
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Space() {
|
export function Space() {
|
||||||
const areas = useAreaStore((state) => state.areas);
|
const areas = useAreaStore((state) => state.areas);
|
||||||
const center = useAreaStore((state) => state.center);
|
const center = useAreaStore((state) => state.center);
|
||||||
|
|
@ -18,8 +85,12 @@ export function Space() {
|
||||||
return new THREE.Vector2(x, y);
|
return new THREE.Vector2(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
const areaMap = () => {
|
const areaData = () => {
|
||||||
const result = [];
|
const result: Array<{
|
||||||
|
shape: THREE.Shape;
|
||||||
|
extrudeSettings: any;
|
||||||
|
tags: any;
|
||||||
|
}> = [];
|
||||||
areas.forEach((bld: any) => {
|
areas.forEach((bld: any) => {
|
||||||
if (!bld.geometry || bld.geometry.length < 3) return;
|
if (!bld.geometry || bld.geometry.length < 3) return;
|
||||||
const shapePoints = bld.geometry.map((pt: any) =>
|
const shapePoints = bld.geometry.map((pt: any) =>
|
||||||
|
|
@ -30,20 +101,25 @@ export function Space() {
|
||||||
}
|
}
|
||||||
const shape = new THREE.Shape(shapePoints);
|
const shape = new THREE.Shape(shapePoints);
|
||||||
let heightValue = parseFloat(bld.tags.height || "");
|
let heightValue = parseFloat(bld.tags.height || "");
|
||||||
|
const heightLevels = parseFloat(bld.tags["building:levels"] || "");
|
||||||
if (isNaN(heightValue)) {
|
if (isNaN(heightValue)) {
|
||||||
heightValue = 10;
|
heightValue = 10;
|
||||||
}
|
}
|
||||||
|
if (!isNaN(heightLevels)) {
|
||||||
|
heightValue = heightLevels * 2.2;
|
||||||
|
}
|
||||||
const extrudeSettings = {
|
const extrudeSettings = {
|
||||||
steps: 1,
|
steps: 1,
|
||||||
depth: heightValue,
|
depth: heightValue,
|
||||||
bevelEnabled: false,
|
bevelEnabled: false,
|
||||||
};
|
};
|
||||||
result.push([shape, extrudeSettings]);
|
result.push({ shape, extrudeSettings, tags: bld.tags });
|
||||||
});
|
});
|
||||||
console.log(result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildingsData = areaData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Canvas camera={{ fov: 90, near: 0.1, far: 4000 }}>
|
<Canvas camera={{ fov: 90, near: 0.1, far: 4000 }}>
|
||||||
<ambientLight intensity={Math.PI / 2} />
|
<ambientLight intensity={Math.PI / 2} />
|
||||||
|
|
@ -54,12 +130,13 @@ export function Space() {
|
||||||
decay={0}
|
decay={0}
|
||||||
intensity={Math.PI}
|
intensity={Math.PI}
|
||||||
/>
|
/>
|
||||||
|
{buildingsData.map((item, index) => (
|
||||||
{areaMap().map((item, index) => (
|
<Building
|
||||||
<mesh key={index} rotation={[-Math.PI / 2, 0, 0]}>
|
key={index}
|
||||||
<extrudeGeometry args={[item[0], item[1]]} />
|
shape={item.shape}
|
||||||
<meshStandardMaterial color="gray" />
|
extrudeSettings={item.extrudeSettings}
|
||||||
</mesh>
|
tags={item.tags}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
<pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
|
<pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
|
||||||
<OrbitControls />
|
<OrbitControls />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue