Add mobile design

This commit is contained in:
Fuhrmann 2025-03-17 15:20:35 +01:00
parent 913af8fba6
commit 7d197d73ef
4 changed files with 61 additions and 8 deletions

View file

@ -36,7 +36,7 @@ function Toggle({
defaultChecked={defaultChecked ? true : false}
/>
<div className="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600 dark:peer-checked:bg-blue-600"></div>
<span className="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300">
<span className="ms-3 text-xs xl:text-sm font-medium text-gray-900 dark:text-gray-300">
{title}
</span>
</label>
@ -191,9 +191,23 @@ export function Form() {
}
}
function handleExport() {
if (!sceneView) return;
sceneView.exportOBJ();
}
return (
<div className="w-full max-h-full flex flex-col gap-2">
<div className="w-full h-full flex flex-col gap-3 p-4 border border-gray-200 rounded shadow">
<div className="w-full h-full flex flex-col gap-3 p-2 border border-gray-200 rounded shadow">
<div className="w-full flex justify-end">
<button
onClick={handleExport}
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 hover:cursor-pointer"
>
Export as .obj
</button>
</div>
<div className="border border-gray-200 rounded grid grid-cols-2 gap-y-2 p-2">
<Toggle title="Slicing Box" onChange={handleChange} />
<Toggle title="Virtual Profile" onChange={handleDrilling} />

View file

@ -39,7 +39,7 @@ export function Map() {
}, [divRef, setSceneView]);
return (
<div className="w-full h-full flex flex-col justify-center">
<div className="w-full h-full">
<div className="w-full h-full" ref={divRef}></div>
</div>
);

View file

@ -1,18 +1,42 @@
"use client";
import { Map } from "./components/Map";
import { Form } from "./components/Form";
import { SceneViewProvider } from "./providers/scene-view-provider";
import { useState } from "react";
export default function Home() {
const [isFormOpen, setIsFormOpen] = useState<boolean>(false);
return (
<div className="w-screen h-screen">
<main className="h-screen">
<main className="h-screen flex flex-col">
<SceneViewProvider>
<div className="flex h-full">
<div className="sm:hidden p-4 bg-white shadow-md flex justify-between items-center">
<span className="text-lg font-semibold">3D-Viewer</span>
<button
onClick={() => setIsFormOpen(true)}
className="text-3xl hover:cursor-pointer"
>
</button>
</div>
<div className="flex-1 flex min-h-0">
<div className="flex-1">
<Map></Map>
</div>
<div className="w-[480px] p-4 flex flex-col items-center border-l border-gray-200">
<Form></Form>
<div
className={`fixed inset-0 bg-white p-2 flex flex-col items-center border-l border-gray-200 shadow-lg transition-transform duration-300 sm:static w-full sm:w-[350px] xl:w-[480px] sm:translate-x-0 ${
isFormOpen ? "translate-x-0" : "translate-x-full"
} sm:translate-x-0`}
>
<button
className="self-end text-gray-500 sm:hidden text-3xl hover:cursor-pointer mb-1 mr-1"
onClick={() => setIsFormOpen(false)}
>
</button>
<Form />
</div>
</div>
</SceneViewProvider>

View file

@ -20,7 +20,7 @@ import {
buildClippingplanes,
} from "./utils/build-clipping-planes";
import { buildCoordinateGrid } from "./utils/build-coordinate-grid";
import { DragControls } from "three/examples/jsm/Addons.js";
import { DragControls, OBJExporter } from "three/examples/jsm/Addons.js";
import { MapTilerProvider, MapView, OpenStreetMapsProvider } from "geo-three";
import { CustomMapHeightNodeShader } from "./CustomMapHeightNodeShader";
import { Data, createSVG } from "./utils/create-borehole-svg";
@ -286,6 +286,21 @@ export class SceneView extends EventTarget {
this._scene.remove(o);
}
}
// Function to export the group as an OBJ file
public exportOBJ() {
const exporter = new OBJExporter();
const objString = exporter.parse(this._model);
// Create a Blob and trigger a download
const blob = new Blob([objString], { type: "text/plain" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "geologic_model.obj";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
async function init(container: HTMLElement, modelId = MODEL_ID) {