I want to display an Html annotation in the center of a bounding box (or sphere) of selected geometry.
(Like this HTML annotations - CodeSandbox)
But in my case I’m loading an external file that contains multiple geometries and I don’t want to load each part separately. Is there a good way to deal with this?
If you don’t mind, it would be helpful if you could show the specific code.
Below is an example sandbox URL and code.
const mat = new THREE.MeshStandardMaterial({ color: "orange" });
const Model = (props) => {
const objRef = useRef();
//Load Rhino3dm object
const object = useLoader(Rhino3dmLoader, "./rhino_logo.3dm", (loader) => {
loader.setLibraryPath("https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/");
});
//Init material
useLayoutEffect(() => {
object.traverse((o) => {
if (o.isMesh) {
o.material = mat;
}
});
});
return (
<primitive
ref={objRef}
castShadow
receiveShadow
onClick={(e) => {
e.stopPropagation();
props.setSelected(e.object.geometry);
}}
onPointerMissed={(e) => {
props.setSelected(null);
}}
object={object}
{...props}
/>
);
};
//I want to put an Html tag in the middle of the bounding box(or sphere) of the selected geometry.
function HtmlAnnotation(props) {
if (props.selected == null) return <></>;
//const pos = props.selected.boundingSphere.center;
return (
<mesh geometry={props.selected} {...props}>
<BBAnchor anchor={[0, 0, 0]}>
<Html distanceFactor={3} center>
<div className="content">
hello <br />
world
</div>
</Html>
</BBAnchor>
</mesh>
);
}
export default function App() {
const [selected, setSelected] = useState(null);
return (
<div className="App">
<Canvas>
<Suspense fallback={null}>
<Model
selected={selected}
setSelected={setSelected}
scale={0.1}
rotation={[-Math.PI / 2, 0, 0]}
/>
<Environment preset="sunset" background />
<HtmlAnnotation
selected={selected}
scale={0.1}
rotation={[-Math.PI / 2, 0, 0]}
/>
</Suspense>
<OrbitControls />
</Canvas>
</div>
);
}