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 requestBuildings = () => {
console.log(area);
const south = area[1].lat;
const west = area[1].lng;
const north = area[0].lat;
@ -50,7 +49,29 @@ export function BuildingHeights({ area }: { area: any }) {
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
css={css({
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 { useAreaStore } from "@/state/areaStore";
import { OrbitControls } from "@react-three/drei";
import { OrbitControls, Html } from "@react-three/drei";
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() {
const areas = useAreaStore((state) => state.areas);
const center = useAreaStore((state) => state.center);
@ -18,8 +85,12 @@ export function Space() {
return new THREE.Vector2(x, y);
}
const areaMap = () => {
const result = [];
const areaData = () => {
const result: Array<{
shape: THREE.Shape;
extrudeSettings: any;
tags: any;
}> = [];
areas.forEach((bld: any) => {
if (!bld.geometry || bld.geometry.length < 3) return;
const shapePoints = bld.geometry.map((pt: any) =>
@ -30,20 +101,25 @@ export function Space() {
}
const shape = new THREE.Shape(shapePoints);
let heightValue = parseFloat(bld.tags.height || "");
const heightLevels = parseFloat(bld.tags["building:levels"] || "");
if (isNaN(heightValue)) {
heightValue = 10;
}
if (!isNaN(heightLevels)) {
heightValue = heightLevels * 2.2;
}
const extrudeSettings = {
steps: 1,
depth: heightValue,
bevelEnabled: false,
};
result.push([shape, extrudeSettings]);
result.push({ shape, extrudeSettings, tags: bld.tags });
});
console.log(result);
return result;
};
const buildingsData = areaData();
return (
<Canvas camera={{ fov: 90, near: 0.1, far: 4000 }}>
<ambientLight intensity={Math.PI / 2} />
@ -54,12 +130,13 @@ export function Space() {
decay={0}
intensity={Math.PI}
/>
{areaMap().map((item, index) => (
<mesh key={index} rotation={[-Math.PI / 2, 0, 0]}>
<extrudeGeometry args={[item[0], item[1]]} />
<meshStandardMaterial color="gray" />
</mesh>
{buildingsData.map((item, index) => (
<Building
key={index}
shape={item.shape}
extrudeSettings={item.extrudeSettings}
tags={item.tags}
/>
))}
<pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
<OrbitControls />