When using Spatialstrates, code from other fragments can be imported using the import keywords in connection with a CSS selector. For example, to import the <TodoItem> component from a fragment with the id todo-item-component the following code can be used:
import { TodoItem } from '#todo-item-component';
export function MyOtherComponent() {
return <TodoItem />;
}In order for Spatialstrates to render new components that are generated by the user, it provides a Dynamic Components mechanism, which automatically scans the webstrate for new fragments with components that should be rendered in the scene. For components to be rendered in the scene, they have to be part of a "JavascriptBabel" (data-type="text/javascript+babel") code fragment with either of the following classes:
| Selector | Description |
|---|---|
.dynamic-gui-component |
2D GUI components that are rendered in the GUI of Spatialstrates, e.g., the Menu or the Spatialstrates logo. |
.dynamic-scene-component |
3D scene components that are rendered in the 3D scene view of Spatialstrates. |
.dynamic-movable-scene-component |
Movable components for the 3D scene view. |
.dynamic-canvas-component |
2D canvas components that are rendered in the 2D canvas view of Spatialstrates. |
.dynamic-shape-component |
ShapeUtil classes (for tldraw) for custom shapes that should be enabled in the 2D canvas view. |
For each dynamic component the App component will attempt to render its Main() function. This function should be exported in the dynamic component like this:
export function Main() {
return <div>What to render in the scene or 2D GUI.</div>;
}Whenever code within the dynamic component is changed, the App component will automatically re-render the component in the scene. This allows for live coding and immediate feedback in the scene—even across devices.
See here for the documentation of the menu component.
See here for the documentation of the controller menu component.
Varv is used as the persisted data store in Spatialstrates. To better integrate Varv into React, there is a small API to access Varv concept instances and properties from within React components (see code here).
A component that renders its children for each concept instance found for the given concept or property. The concept, property, and if parameters work similar to how the DOM View in Varv works (see here).
| Parameter | Description |
|---|---|
children |
The child components that should be rendered for each concept instance found for the given concept or property. |
concept |
The concept, whose concept instances should be rendered. |
property |
The property of a concept instance, whose concept instances should be rendered. |
if |
Takes a property name of a boolean property. Only concept instances where this property is true are rendered. |
<Varv concept="conceptName">
<MyComponent />
</Varv>A hook to access the value of a property of a concept instance. It can only be used within a <Varv> component. The value is updated whenever the property changes and works similar to React's useState hook.
| Parameter | Description |
|---|---|
propertyName |
The name of the property to access. |
const [value, setValue] = useProperty('propertyName');Warning
This section is outdated. The new version of Spatialstrates requires both a 3D component and 2D shape to use movables across both the 3D scene and 2D canvas views.
Movables are a class of components that are placed in the 3D scene and that have their position and rotation persisted and synchronized using Varv.
Movables rely on Varv for sharing and persisting their location and rotation across clients. To use them, it is required to add a concept definition. See the example below for how to define a concept for a new movable component.
The Movable component is a wrapper for other movable components. It handles grabbing events and synchronization of the position and rotation of the movable with the data store.
All children of the Movable component will be moved when the Movable is dragged. The handle of a Movable describes the part of a movable that can be dragged. For example, when creating a board game, the board could be the handle to move it, while the pieces on the board would be the children of the Movable and provide their own interactive behavior. But also the whole component can be the handle, this is, for instance, the case for the sticky note, trashcan, and image.
It can be imported from '#Movable .default'.
| Parameter | Description |
|---|---|
children |
The children of the movable. |
handle |
The handle of the movable. |
upright |
Whether the movable should be upright or not. If true, it will only rotate around the y-axis. |
onDragStart |
The function to call when the movable is started to be dragged. |
onDragEnd |
The function to call when the movable is stopped to be dragged. |
onDragging |
The function to call when the movable is being dragged. |
Creates a new movable concept instance of the given concept type with the given properties. The new movable is placed in front of the current camera position by default.
It can be imported from '#Movable .helpers'.
| Parameter | Description |
|---|---|
concept |
The name of the concept that should be created. |
properties |
An object with property values for the new movable. |
The following properties are available in concept instances that are derived from the Movable concept:
| Property | Description |
|---|---|
position |
The position of the movable in the 3D scene. |
rotation |
The rotation of the movable in the 3D scene. |
selected |
Whether the movable is selected or not. |
hovered |
Whether the movable is hovered or not. |
beingDragged |
Whether the movable is being dragged or not. |
{
"concepts": {
"MyMovable": {
"schema": {
"myProperty": "string"
},
"extensions": {
"inject": [ "Movable" ]
}
}
}
}import React from 'react';
const { useMemo } = React;
import { Varv, useProperty } from '#VarvReact';
import { Movable } from '#Movable .default';
import { Text } from '#Text .default';
function MyMovable() {
const [myProperty, setMyProperty] = useProperty('myProperty');
const handle = useMemo(() => <Box args={[0.15, 0.15, 0.15]}>
<meshStandardMaterial color="red" />
</Box>, []);
return <Movable handle={handle} upright={false}>
<Text>{myProperty}</Text>
</Movable>;
}
export function Main() {
return <Varv concept="MyMovable">
<MyMovable />
</Varv>;
}