Html
Allows you to tie HTML content to any object of your scene. It will be projected to the objects whereabouts automatically.
<Html
as='div' // Wrapping element (default: 'div')
wrapperClass // The className of the wrapping element (default: undefined)
prepend // Project content behind the canvas (default: false)
center // Adds a -50%/-50% css transform (default: false) [ignored in transform mode]
fullscreen // Aligns to the upper-left corner, fills the screen (default:false) [ignored in transform mode]
distanceFactor={10} // If set (default: undefined), children will be scaled by this factor, and also by distance to a PerspectiveCamera / zoom by a OrthographicCamera.
zIndexRange={[100, 0]} // Z-order range (default=[16777271, 0])
portal={domnodeRef} // Reference to target container (default=undefined)
transform // If true, applies matrix3d transformations (default=false)
sprite // Renders as sprite, but only in transform mode (default=false)
calculatePosition={(el: Object3D, camera: Camera, size: { width: number; height: number }) => number[]} // Override default positioning function. (default=undefined) [ignored in transform mode]
occlude={[ref]} // Can be true or a Ref<Object3D>[], true occludes the entire scene (default: undefined)
onOcclude={(hidden) => null} // Callback when the visibility changes (default: undefined)
{...groupProps} // All THREE.Group props are valid
{...divProps} // All HTMLDivElement props are valid
>
<h1>hello</h1>
<Grid cols={4}>world</Grid>
</Html>
Html can hide behind geometry using the occlude
prop.
<Html occlude />
When the Html object hides it sets the opacity prop on the innermost div. If you want to animate or control the transition yourself then you can use onOcclude
.
const [hidden, set] = useState()
<Html
occlude
onOcclude={set}
style={{
transition: 'all 0.5s',
opacity: hidden ? 0 : 1,
transform: `scale(${hidden ? 0.5 : 1})`
}}
/>
Blending occlusion
Html can hide behind geometry as if it was part of the 3D scene using this mode. It can be enabled by using "blending"
as the occlude
prop.
// Enable real occlusion
<Html occlude="blending" />
You can also give HTML material properties using the material
prop.
<Html
occlude
material={
<meshPhysicalMaterial
side={DoubleSide} // Required
opacity={0.1} // Degree of influence of lighting on the HTML
... // Any other material properties
/>
}
/>
Enable shadows using the castShadow
and recieveShadow
prop.
Note: Shadows only work with a custom material. Shadows will not work with
meshBasicMaterial
andshaderMaterial
by default.
<Html
occlude
castShadow // Make HTML cast a shadow
receiveShadow // Make HTML receive shadows
material={<meshPhysicalMaterial side={DoubleSide} opacity={0.1} />}
/>
Note: Html 'blending' mode only correctly occludes rectangular HTML elements by default. Use the
geometry
prop to swap the backing geometry to a custom one if your Html has a different shape.
If transform mode is enabled, the dimensions of the rendered html will depend on the position relative to the camera, the camera fov and the distanceFactor. For example, an Html component placed at (0,0,0) and with a distanceFactor of 10, rendered inside a scene with a perspective camera positioned at (0,0,2.45) and a FOV of 75, will have the same dimensions as a "plain" html element like in this example.
A caveat of transform mode is that on some devices and browsers, the rendered html may appear blurry, as discussed in #859. The issue can be at least mitigated by scaling down the Html parent and scaling up the html children:
<Html transform scale={0.5}>
<div style={{ transform: 'scale(2)' }}>Some text</div>
</Html>