Space Component

The Space component is a core component that renders and manages an interactive 3D space viewer. It handles camera controls, model interactions, and various viewing modes.

Basic Usage

If you just want the base version of boundary explore, with all its features all you have to do is this:

<Space tourId="example-tour"/>

You can also be more explicit with the features you want by overriding the html overlay and the 3d scene content. Each feature in boundary explore is a react component. So

import {Space, Overlay,Loading,FloorplanModal,TagModal,Toolbar,Tags,Hotspots,Measurements} from "@the-boundary/sdk"
 
//--- the rest of the app ---
 
<Space tourId="example-tour">
	<Overlay>
		<Loading/>
		<FloorplanModal/>
		<TagModal/>
		<Toolbar/>
	</Overlay>
	<Scene>
		<Tags />
		<Hotspots/>
		<Measurements />
		{/*add any other fiber content here*/}
	</Scene>
</Space>
⚠️

When using the Scene and Overlay components, it will override all default components. You’ll need to explicitly add back built in components you want to keep, like Tags, Hotspots, and Measurements etc.

You can now create any react component html or fiber and inject it into the sdk. This is quite a powerful feature. It allows you to place 3d objects into the tour.

Examples

Basic Tour

<Space
tourId="example-tour"
style={{ width: '100%', height: '500px' }}
onJumpEnd={(camera) => console.log('Camera jump completed', camera)}
/>

Tour with Custom Overlay Design

<Space
				tourId="cm3n04tge0000svl3086s6wuv"
				style={{ width: '100%', height: '600px' }}
				
			>
				<Overlay>
					<FloorplanModal
					showCameras
					title={"4 Bed Villa"}
					subtitle={"Select a room"}
					floorItemBuilder={(room,selected,onClick)=><button 
						onClick={onClick}
						style={{
						border:"none",
						color:"white",
						padding:"8px 10px",
						fontSize:"18px",
						textAlign:"left",
						width:"100%",
						cursor:"pointer",
						pointerEvents:"all",
						background: selected? "rgba(255,255,255,0.1)":"none",
							borderLeft:selected ? "solid 4px rgb(0,100,255)":"solid 4px rgba(0,0,0,0)",
							paddingLeft:"20px"
						}}>
 
						{room.name}
					</button>}
					roomItemBuilder={(room,selected,onClick)=><button 
						onClick={onClick}
						style={{
						
						border:"none",
						color:"white",
						padding:10,
						width:"100%",
						textAlign:"left",
						background: selected? "rgba(255,255,255,0.2)":"none",
						fontSize:"15px",
						fontWeight:"300",
							borderLeft:selected ? "solid 4px rgb(0,200,255)":"solid 4px rgba(0,0,0,0)",
							paddingLeft:"20px"
						}}>
 
						{room.name}
					</button>}
						borderRadius={0}
						sidebarProps={{
							style:{
								"background": "rgba(0,0,0,0.1)",
								"borderRadius":"0px",
								"padding":"0px",
								"color":"white",
								border:"none",
								"backdropFilter": "blur(20px)",
							}
						}}
						
					/>
					
					<Toolbar 
					labelColor='white'
					style={{
						"background": "rgba(0,0,0,0.1)",
						"borderRadius":"0px",
						"padding":"10px",
						border:"none",
						"backdropFilter": "blur(20px)",
					}}
					variant={'right-center'} />
				</Overlay>
 
				
			</Space>

Tour in slave mode

Master Tour

Slave Tour

import { Space } from '@viewform/sdk';
 
//Variables to sync between slave and master
const [slaveMeasurements,setSlaveMeasurements] = useState([])
  const slaveRotation = useRef<Euler>(new Euler(0,0,0,"YXZ"))
  const slaveZoom = useRef<number>(0)
 
  const [slaveFloorplanState,setFloorplanState] = useState({
    open:false,
    floorId:undefined
  })
  const [slaveKeyframe,setSlaveKeyframe] = useState<Keyframe|undefined>()
 
  //Function to update the slave state
 
const onRotationChange = useCallback((rotation)=>{
    slaveRotation.current = rotation.clone()
  },[])
 
    const onFovChange = useCallback((fov)=>{
        slaveZoom.current = fov
    },[])
 
    const onKeyframe = useCallback((keyframe)=>{
        setSlaveKeyframe(keyframe)
    },[])
 
    const onFloorplanStateChange = useCallback((state)=>{
        setFloorplanState(state)
    },[])
 
    const onMeasurements = useCallback((measurements)=>{
        setSlaveMeasurements(measurements)
    },[])
    //SLAVE
 
    <Space 
        tourId={"cm41fa65900001ycoxqbofdbp"}
        slave={slave}       
        slaveRotation={slaveRotation} //pass a rotation ref to bypass all react updates and shoot it straight into the render loop at 120fps
        slaveZoom={slaveZoom} //same as above
        slaveState={slaveKeyframe}
      >
        <Overlay>
			<FloorplanModal
            floorId={slaveFloorplanState?.floorId}
            open={slaveFloorplanState?.open}/>	
            <Loading/>
		</Overlay>
 
		<Scene>
			<Measurements data={slaveMeasurements}/>
		</Scene>
    </Space>
 
 
 
    //MASTER
 
    <Space 
        tourId={"cm41fa65900001ycoxqbofdbp"}
        onRotationChange={onRotationChange}
        onZoomChange={ onFovChange}
        onKeyframe={onJumpStart}
      >
        <Overlay>
			<FloorplanModal onChange={onFloorplanStateChange}/>
			<Toolbar/>
            <Loading/>
		</Overlay>
 
		<Scene>
			<Measurements onChange={onMeasurements}/>
		</Scene>
    </Space>
 

Props

Data Source Options

PropTypeDefaultDescription
tourIdstring-Unique identifier to fetch tour data
tourIViewformTour-Direct tour data object
pathstring-Local path to load tour data

Camera Settings

PropTypeDefaultDescription
resolutionResolution-Forces maximum resolution for tour
startVersionIdstring-Initial version ID to load
startCameraIdstring-Initial camera position ID
startCameraRotationIEuler-Initial camera rotation
startCameraFovnumber-Initial field of view
lockFovboolean-Prevents FOV changes

Slave Mode Settings

PropTypeDefaultDescription
slavebooleanfalseEnables slave mode
slaveStateKeyframe-Current keyframe state in slave mode
slaveRotationMutableRefObject<Euler>-Rotation reference in slave mode
slaveZoomMutableRefObject<number>-Zoom reference in slave mode

Camera Navigation Settings

PropTypeDefaultDescription
jumpModeJumpMode-Camera transition mode
enableCameraPitchRotationbooleanfalseEnables pitch rotation
enableYawCorrectionbooleanfalseEnables yaw correction
enablePitchCorrectionbooleanfalseEnables pitch correction
requireCubemapToJumpbooleanfalseRequires cubemap for jumps

Model Settings

PropTypeDefaultDescription
materialOverrideMaterial-Override model materials
modelViewTypeModelViewType-Model viewing mode

Event Handlers

PropTypeDescription
onModelClick(e: any) => voidTriggered when model is clicked
onModelPointerMove(e: any) => voidTriggered when pointer moves over model
onModelPointerEnter(e: any) => voidTriggered when pointer enters model
onModelPointerLeave(e: any) => voidTriggered when pointer leaves model
onZoomChange(value: number) => voidTriggered on zoom changes
onRotationChange(value: Euler) => voidTriggered on rotation changes
onRotationStart(value: Euler) => voidTriggered when rotation starts
onRotationEnd(value: Euler) => voidTriggered when rotation ends
onJumpStart(current: ICameraDetails, next: ICameraDetails) => voidTriggered when camera jump starts
onJumpEnd(current: ICameraDetails) => voidTriggered when camera jump ends
onKeyframe(value: Keyframe) => voidTriggered on keyframe changes

Styling

PropTypeDescription
styleReact.CSSPropertiesCustom CSS styles
classNamestringCustom CSS class name

Other Props

PropTypeDefaultDescription
debugbooleanfalseEnables debug mode
editingbooleanfalseEnables CMS editing mode
childrenReactNode-Child components