@jackinger/react-3d-model-viewer
v1.1.0
Published
A shadcn/ui styled 3D model viewer with annotation, search and highlight support for anatomy models
Maintainers
Readme
react-3d-model-viewer
A shadcn/ui styled 3D model viewer component for React with annotation, search and highlight support.
Features
- 3D Model Viewing: Load GLB/GLTF models with orbit controls
- Annotation System: Add, edit, delete annotations on 3D models
- Structure Search: Search and highlight anatomy structures
- Demo Model: Built-in skull anatomy demo model
- Comments: Add comments to annotations
- Responsive Design: Works with shadcn/ui styling
Installation
npm install react-3d-model-viewerPeer Dependencies
npm install react react-dom three @react-three/fiber @react-three/dreiQuick Start
import { CompleteModelViewer } from 'react-3d-model-viewer'
export default function App() {
return (
<div className="h-[600px]">
<CompleteModelViewer
modelUrl="/models/skull.glb"
structuresList={['Cranium', 'Frontal Bone', 'Temporal Bone']}
showSearchBar={true}
/>
</div>
)
}Usage
Basic Usage (Demo Model)
import { CompleteModelViewer } from 'react-3d-model-viewer'
function App() {
return <CompleteModelViewer />
}With Custom GLB Model
import { CompleteModelViewer } from 'react-3d-model-viewer'
function App() {
return (
<CompleteModelViewer
modelUrl="/models/anatomy.glb"
showSearchBar={true}
structuresList={['Skull', 'Mandible', 'Spine']}
/>
)
}With Annotations
import { CompleteModelViewer, type Annotation } from 'react-3d-model-viewer'
const initialAnnotations: Annotation[] = [
{
id: '1',
structureName: 'Cranium',
position: { x: 0, y: 0.8, z: 0 },
label: 'Skull',
color: '#ff6b6b',
},
]
function App() {
return (
<CompleteModelViewer
modelUrl="/models/skull.glb"
initialAnnotations={initialAnnotations}
onSaveAnnotation={(data) => console.log('Save:', data)}
onDeleteAnnotation={(ann) => console.log('Delete:', ann)}
/>
)
}Using Individual Components
import { ModelViewer } from 'react-3d-model-viewer/ModelViewer'
function App() {
return (
<ModelViewer
modelUrl="/models/skull.glb"
annotations={[]}
highlightedStructures={[]}
onAnnotationClick={(ann) => console.log(ann)}
onModelPartClick={(mesh, point) => console.log(mesh, point)}
/>
)
}API Reference
CompleteModelViewer
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| modelUrl | string | - | GLB model URL (empty shows demo) |
| initialAnnotations | Annotation[] | [] | Initial annotation list |
| showSearchBar | boolean | true | Show/hide search bar |
| structuresList | string[] | [] | Structure names for search |
| currentUserId | string | - | Current user ID for comments |
| onSaveAnnotation | function | - | Callback when annotation saved |
| onDeleteAnnotation | function | - | Callback when annotation deleted |
| onAddComment | function | - | Callback when comment added |
| onModelPartClick | function | - | Callback when model part clicked |
| onHighlightChange | function | - | Callback when highlight changes |
ModelViewer
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| modelUrl | string | - | GLB model URL |
| annotations | Annotation[] | [] | Annotation list |
| highlightedStructures | HighlightedStructure[] | [] | Structures to highlight |
| selectedAnnotationId | string | - | Currently selected annotation |
| showGrid | boolean | true | Show/hide grid |
| backgroundColor | string | #1a1a2e | Canvas background |
AnnotationPanel
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| annotation | Annotation | - | Current annotation |
| isCreating | boolean | - | Creating new annotation mode |
| newPosition | Position3D | - | New annotation position |
| onSave | function | - | Save callback |
| onDelete | function | - | Delete callback |
| onAddComment | function | - | Add comment callback |
SearchBar
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| structuresList | string[] | - | Structure names |
| onSearchResults | function | - | Search results callback |
| isSearching | boolean | - | Loading state |
| placeholder | string | - | Placeholder text |
Types
interface Annotation {
id: string
structureName: string
position: Position3D
label?: string | null
description?: string | null
color: string
meshName?: string | null
comments?: Comment[]
}
interface Position3D {
x: number
y: number
z: number
}
interface HighlightedStructure {
meshName?: string
structureName: string
color?: string
}Styling
This component uses Tailwind CSS classes. Make sure your project has Tailwind configured:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pAdd the content paths to your tailwind.config.js:
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
// ... rest of config
}License
MIT
