Finish virtual profile
This commit is contained in:
parent
46db218492
commit
913af8fba6
3 changed files with 298 additions and 132 deletions
|
@ -1,6 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { ChangeEvent, ReactNode, useContext, useRef, useState } from "react";
|
||||
import {
|
||||
ChangeEvent,
|
||||
ReactNode,
|
||||
forwardRef,
|
||||
useContext,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import {
|
||||
SceneViewContext,
|
||||
|
@ -15,7 +23,7 @@ function Toggle({
|
|||
defaultChecked,
|
||||
}: {
|
||||
title: string;
|
||||
onChange: (e: any) => void;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
defaultChecked?: boolean;
|
||||
}) {
|
||||
return (
|
||||
|
@ -35,68 +43,95 @@ function Toggle({
|
|||
);
|
||||
}
|
||||
|
||||
function Accordion({
|
||||
children,
|
||||
title,
|
||||
}: {
|
||||
children?: ReactNode;
|
||||
enum Position {
|
||||
Start,
|
||||
Center,
|
||||
End,
|
||||
}
|
||||
|
||||
interface AccordionRef {
|
||||
open: (b: boolean) => void;
|
||||
}
|
||||
|
||||
interface AccordionProps {
|
||||
title: string;
|
||||
}) {
|
||||
const [expanded, setExpanded] = useState<boolean>(true);
|
||||
const accordionBodyRef = useRef<HTMLDivElement>(null);
|
||||
position: Position;
|
||||
open: boolean;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
if (!accordionBodyRef.current) return;
|
||||
const Accordion = forwardRef<AccordionRef, AccordionProps>(
|
||||
({ children, title, position, open }, ref) => {
|
||||
const [expanded, setExpanded] = useState<boolean>(open);
|
||||
const accordionBodyRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
accordionBodyRef.current.classList.toggle("hidden");
|
||||
setExpanded(!expanded);
|
||||
}
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: (b: boolean) => setExpanded(b),
|
||||
}));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 id="accordion-collapse-heading-1">
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center justify-between w-full p-5 font-medium rtl:text-right text-gray-500 border border-b-0 border-gray-200 rounded-t focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3 hover:cursor-pointer"
|
||||
data-accordion-target="#accordion-collapse-body-1"
|
||||
aria-expanded={expanded ? "true" : "false"}
|
||||
aria-controls="accordion-collapse-body-1"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span>{title}</span>
|
||||
<svg
|
||||
data-accordion-icon
|
||||
className="w-3 h-3 rotate-180 shrink-0"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
function handleClick() {
|
||||
if (!accordionBodyRef.current) return;
|
||||
|
||||
setExpanded(!expanded);
|
||||
}
|
||||
|
||||
const className =
|
||||
position === Position.Center
|
||||
? "flex items-center justify-between w-full p-5 font-medium rtl:text-right text-gray-500 border border-b border-gray-200 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3 hover:cursor-pointer"
|
||||
: "flex items-center justify-between w-full p-5 font-medium rtl:text-right text-gray-500 border border-b border-gray-200 rounded-t focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3 hover:cursor-pointer";
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 id="accordion-collapse-heading-1">
|
||||
<button
|
||||
type="button"
|
||||
className={className}
|
||||
data-accordion-target="#accordion-collapse-body-1"
|
||||
aria-expanded={expanded ? "true" : "false"}
|
||||
aria-controls="accordion-collapse-body-1"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5 5 1 1 5"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</h2>
|
||||
<div
|
||||
id="accordion-collapse-body-1"
|
||||
ref={accordionBodyRef}
|
||||
aria-labelledby="accordion-collapse-heading-1"
|
||||
>
|
||||
<div className="p-5 border border-gray-200 dark:border-gray-700 dark:bg-gray-900">
|
||||
{children}
|
||||
<span>{title}</span>
|
||||
<svg
|
||||
data-accordion-icon
|
||||
className={
|
||||
expanded ? "w-3 h-3 shrink-0" : "w-3 h-3 rotate-180 shrink-0"
|
||||
}
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5 5 1 1 5"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</h2>
|
||||
<div
|
||||
id="accordion-collapse-body-1"
|
||||
ref={accordionBodyRef}
|
||||
aria-labelledby="accordion-collapse-heading-1"
|
||||
className={expanded ? "" : "hidden"}
|
||||
>
|
||||
<div className="p-5 border border-gray-200 dark:border-gray-700 dark:bg-gray-900">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
Accordion.displayName = "Accordion";
|
||||
|
||||
export function Form() {
|
||||
const svgContainerRef = useRef<HTMLDivElement>(null);
|
||||
const accordionRef1 = useRef<AccordionRef>(null);
|
||||
const accordionRef0 = useRef<AccordionRef>(null);
|
||||
const { sceneView } = useContext(SceneViewContext) as SceneViewContextType;
|
||||
|
||||
function handleChange() {
|
||||
|
@ -133,11 +168,10 @@ export function Form() {
|
|||
if (!sceneView) return;
|
||||
|
||||
if ((e.target as HTMLInputElement).checked) {
|
||||
sceneView.enableRaycaster();
|
||||
sceneView.addEventListener("svg-created", handleSVGCreated);
|
||||
// Enable raycaster with callback to handle svg element
|
||||
sceneView.enableRaycaster(handleSVGCreated);
|
||||
} else {
|
||||
sceneView.disableRaycaster();
|
||||
sceneView.removeEventListener("svg-created", handleSVGCreated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,61 +183,83 @@ export function Form() {
|
|||
svgContainerRef.current.removeChild(c);
|
||||
}
|
||||
svgContainerRef.current.appendChild(e.detail.element);
|
||||
if (accordionRef0.current) {
|
||||
accordionRef0.current.open(false);
|
||||
}
|
||||
if (accordionRef1.current) {
|
||||
accordionRef1.current.open(true);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full flex flex-col gap-2 overflow-y-auto">
|
||||
<div className="w-full flex flex-col gap-3 p-4 border border-gray-200 rounded shadow">
|
||||
<Toggle title="Slicing Box" onChange={handleChange} />
|
||||
<Toggle title="Drilling Profiler" onChange={handleDrilling} />
|
||||
<Toggle title="Coordinate Grid" onChange={handleChangeCG} />
|
||||
<Toggle title="Wireframe" onChange={handleChangeWireframe} />
|
||||
<Toggle
|
||||
title="Topography (OSM)"
|
||||
onChange={handleChangeTopography}
|
||||
defaultChecked
|
||||
/>
|
||||
<Accordion title="Layers">
|
||||
{
|
||||
<div className="flex flex-col gap-2">
|
||||
{sceneView?.model.children.map((child) => {
|
||||
const key = `toggle-visibility-${child.name}`;
|
||||
const color = `#${(
|
||||
(child as Mesh).material as MeshStandardMaterial
|
||||
).color.getHexString()}`;
|
||||
const visible = (child as Mesh).visible;
|
||||
<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="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} />
|
||||
<Toggle title="Coordinate Grid" onChange={handleChangeCG} />
|
||||
<Toggle title="Wireframe" onChange={handleChangeWireframe} />
|
||||
<Toggle
|
||||
title="Topography (OSM)"
|
||||
onChange={handleChangeTopography}
|
||||
defaultChecked
|
||||
/>
|
||||
</div>
|
||||
<div className="overflow-y-auto">
|
||||
<Accordion
|
||||
title="Layers"
|
||||
position={Position.Start}
|
||||
open={true}
|
||||
ref={accordionRef0}
|
||||
>
|
||||
{
|
||||
<div className="flex flex-col gap-2">
|
||||
{sceneView?.model.children.map((child) => {
|
||||
const key = `toggle-visibility-${child.name}`;
|
||||
const color = `#${(
|
||||
(child as Mesh).material as MeshStandardMaterial
|
||||
).color.getHexString()}`;
|
||||
const visible = (child as Mesh).visible;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className="flex items-center justify-start gap-2.5 border-b border-gray-200 py-1"
|
||||
>
|
||||
<span
|
||||
className="inline-block w-5 h-5 flex-none rounded"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
></span>
|
||||
<input
|
||||
id={key}
|
||||
type="checkbox"
|
||||
onChange={() => handleCheckboxChange(child.name)}
|
||||
className="hover:cursor-pointer"
|
||||
defaultChecked={visible ? true : false}
|
||||
/>
|
||||
<label
|
||||
htmlFor={key}
|
||||
className="antialiased font-light text-gray-700"
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className="flex items-center justify-start gap-2.5 border-b border-gray-200 py-1"
|
||||
>
|
||||
{child.name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
</Accordion>
|
||||
<div ref={svgContainerRef}> </div>
|
||||
<span
|
||||
className="inline-block w-5 h-5 flex-none rounded"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
}}
|
||||
></span>
|
||||
<input
|
||||
id={key}
|
||||
type="checkbox"
|
||||
onChange={() => handleCheckboxChange(child.name)}
|
||||
className="hover:cursor-pointer"
|
||||
defaultChecked={visible ? true : false}
|
||||
/>
|
||||
<label
|
||||
htmlFor={key}
|
||||
className="antialiased font-light text-gray-700"
|
||||
>
|
||||
{child.name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Virtual Profile"
|
||||
position={Position.Center}
|
||||
open={false}
|
||||
ref={accordionRef1}
|
||||
>
|
||||
<div ref={svgContainerRef}> </div>
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue