threlte logo
@threlte/extras

<Text>

The <Text> component uses troika-three-text to render text.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import { Checkbox, Pane, Slider, Textarea } from 'svelte-tweakpane-ui'
  import { DEG2RAD } from 'three/src/math/MathUtils.js'
  import Scene from './Scene.svelte'

  let text = 'Hello\nWorld'
  let bevelEnabled = true
  let bevelOffset = 0
  let bevelSegments = 20
  let bevelSize = 0.2
  let bevelThickness = 0.1
  let curveSegments = 12
  let height = 1
  let size = 5
  let smooth = 0.1
  /*
	rotation.x={-0.28}
      size={5}
      height={1}
      bevelEnabled={true}
      bevelThickness={0.1}
      bevelSize={0.2}
      bevelSegments={20}
      smooth={0.1}
			*/
</script>

<Pane
  title="Text3DGeometry"
  position="fixed"
>
  <Textarea
    bind:value={text}
    label="text"
  />
  <Checkbox
    label="bevelEnabled"
    bind:value={bevelEnabled}
  />
  <Slider
    label="bevelOffset"
    bind:value={bevelOffset}
    min={0}
    max={2}
  />
  <Slider
    label="bevelSegments"
    bind:value={bevelSegments}
    step={1}
    min={0}
    max={50}
  />
  <Slider
    label="bevelSize"
    bind:value={bevelSize}
    min={0}
    max={2}
  />
  <Slider
    label="bevelThickness"
    bind:value={bevelThickness}
    min={0}
    max={2}
  />
  <Slider
    label="curveSegments"
    bind:value={curveSegments}
    step={1}
    min={0}
    max={50}
  />
  <Slider
    label="height"
    bind:value={height}
    min={0}
    max={5}
  />
  <Slider
    label="size"
    bind:value={size}
    min={0}
    max={10}
  />
  <Slider
    label="smooth"
    bind:value={smooth}
    min={0}
    max={180 * DEG2RAD}
  />
</Pane>

<div>
  <Canvas>
    <Scene
      {text}
      {bevelEnabled}
      {bevelOffset}
      {bevelSegments}
      {bevelSize}
      {bevelThickness}
      {curveSegments}
      {height}
      {size}
      {smooth}
    />
  </Canvas>
</div>

<style>
  div {
    height: 100%;
  }
</style>
<script lang="ts">
  import { T } from '@threlte/core'
  import { Align, Environment, Float, OrbitControls, Text3DGeometry } from '@threlte/extras'

  export let text: string
  export let bevelEnabled: boolean
  export let bevelOffset: number
  export let bevelSegments: number
  export let bevelSize: number
  export let bevelThickness: number
  export let curveSegments: number
  export let height: number
  export let size: number
  export let smooth: number
</script>

<Align let:align>
  <T.Mesh>
    <Text3DGeometry
      font={'/fonts/Inter-semibold.blob'}
      {text}
      {bevelEnabled}
      {bevelOffset}
      {bevelSegments}
      {bevelSize}
      {bevelThickness}
      {curveSegments}
      {height}
      {size}
      {smooth}
      on:create={align}
    />
    <T.MeshStandardMaterial
      color="#FD3F00"
      toneMapped={false}
      metalness={1.0}
      roughness={0.1}
    />
  </T.Mesh>
</Align>

<Environment files="/hdr/shanghai_riverside_1k.hdr" />

<Float
  rotationIntensity={[0, 3, 0]}
  rotationSpeed={1}
  floatingRange={[-5, 5]}
  speed={1}
>
  <T.PerspectiveCamera
    makeDefault
    position.y={0}
    position.z={20}
    fov={90}
    on:create={({ ref }) => {
      ref.lookAt(0, 0, 0)
    }}
  >
    <OrbitControls
      enableDamping
      enablePan={false}
      enableZoom={false}
    />
  </T.PerspectiveCamera>
</Float>
<script lang="ts">
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
  import { Pane, Slider, Text } from 'svelte-tweakpane-ui'

  let text = 'hello world'
  let fontSize = 1
</script>

<Pane
  title="Text"
  position="fixed"
>
  <Text bind:value={text} />
  <Slider
    bind:value={fontSize}
    min={0.1}
    max={2}
  />
</Pane>

<div>
  <Canvas>
    <Scene
      {text}
      {fontSize}
    />
  </Canvas>
</div>

<style>
  div {
    height: 100%;
    background-color: rgb(254 61 0 / 0.2);
  }
</style>
<script lang="ts">
  import { T, useTask } from '@threlte/core'
  import { Grid, Text } from '@threlte/extras'

  let rotation = 0

  export let text: string
  export let fontSize: number

  useTask((delta) => {
    const f = 1 / 60 / delta // ~1 at 60fps
    rotation += 0.002 * f
  })
</script>

<T.Group rotation.y={rotation}>
  <T.OrthographicCamera
    zoom={80}
    position={[0, 5, 10]}
    makeDefault
    on:create={({ ref }) => {
      ref.lookAt(0, 0, 0)
    }}
  />
</T.Group>

<Text
  {text}
  color="white"
  {fontSize}
  anchorX="50%"
  anchorY="100%"
/>

<Grid sectionColor="#FF3E00" />

Example

<script>
  import { Text } from '@threlte/extras'
  let value = ''
</script>

<input
  type="text"
  bind:value
/>
<Text text={value} />

<Text> is suspense-ready and will suspend while the font is loading. You can use the characters prop to preload a specific set of characters to prevent FOUC.

<script>
  import { Text, Suspense } from '@threlte/extras'
</script>

<Suspense>
  <Text
    text="HELLO WORLD"
    characters="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  />

  <svelte:fragment slot="fallback">
    <!-- show fallback content while font data is loading -->
  </svelte:fragment>
</Suspense>

Component Signature

<Text> extends <T.Mesh> and supports all its props, slot props, bindings and events.

Props

name
type
required
description

anchorX
number | 'left' | 'center' | 'right' | string
no

anchorY
number | 'top' | 'top-baseline' | 'middle' | 'bottom-baseline' | 'bottom' | string
no

characters
string
no
The set of characters `<Text>` will preload while suspended.

clipRect
[number, number, number, number]
no

color
string | number | Color
no

curveRadius
number
no

depthOffset
number
no

direction
'auto' | 'ltr' | 'rtl'
no

fillOpacity
number
no

font
string
no

fontSize
number
no

glyphGeometryDetail
number
no

letterSpacing
number
no

lineHeight
number | string
no

material
Material | Material[]
no

maxWidth
number
no

outlineBlur
number | string
no

outlineColor
ColorRepresentation
no

outlineOffsetX
number | string
no

outlineOffsetY
number | string
no

outlineOpacity
number
no

outlineWidth
number | string
no

overflowWrap
'normal' | 'break-word' | 'normal'
no

sdfGlyphSize
number
no

strokeColor
ColorRepresentation | Color
no

strokeOpacity
number
no

strokeWidth
number | string
no

text
string
no

textAlign
'left' | 'right' | 'center' | 'justify'
no

textIndent
number
no

whiteSpace
'normal' | 'nowrap' | 'pre-wrap'
no