feat: float detail box

This commit is contained in:
Huh Hyeongjun 2025-02-25 11:55:15 +09:00
parent 719a2eac00
commit cfc19a42a2
2 changed files with 112 additions and 14 deletions

View File

@ -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",

View File

@ -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 />