threlte logo
@threlte/extras

<Text3DGeometry>

Render 3D text as a geometry using threejs’s TextGeometry.

<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>

Examples

Basic Example

Scene.svelte
<script lang="ts">
  import { T } from '@threlte/core'
  import { Text3DGeometry } from '@threlte/extras'
</script>

<T.Mesh>
  <Text3DGeometry text={'Hello World'} />
  <T.MeshStandardMaterial />
</T.Mesh>

Using a Custom Font

If no font property is provided, the default font “Helvetiker” will be used and loaded from the CDN JSDeliver.

If you want to use a custom font, you can generate a font using typeface.js. Provide the path to the resulting JSON file using the prop font.

Suspense-Ready

The component <Text3DGeometry> is suspense-ready. Using it in a <Suspense> boundary will suspend rendering until the provided font is loaded:

Scene.svelte
<script lang="ts">
  import { T } from '@threlte/core'
  import { Text3DGeometry, Suspense } from '@threlte/extras'
  import Fallback from './Fallback.svelte'
</script>

<Suspense>
  <T.Mesh>
    <Text3DGeometry
      font={'path-to-your-font'}
      text={'Hello World'}
    />
    <T.MeshStandardMaterial />
  </T.Mesh>

  <Fallback slot="fallback" />
</Suspense>

Loading a Font Yourself

You can also load the font yourself and pass it to the component, like so:

Scene.svelte
<script lang="ts">
  import { T, useLoader } from '@threlte/core'
  import { Text3DGeometry } from '@threlte/extras'
  import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'

  let font = useLoader(FontLoader).load('path-to-your-font')
</script>

{#if $font}
  <T.Mesh>
    <Text3DGeometry
      font={$font}
      text={'Hello World'}
    />
    <T.MeshStandardMaterial />
  </T.Mesh>
{/await}

Centering Text

You can center a text by using the <Align> component and calling the align slot prop when the text geometry is created.

Scene.svelte
<Align let:align>
  <T.Mesh>
    <Text3DGeometry
      font={'path-to-your-font'}
      text={`Hello!`}
      on:create={align}
    />
    <T.MeshStandardMaterial />
  </T.Mesh>
</Align>

Smoothing Text

You can smooth the text by setting the smooth prop to a value above 0 to smooth all edges where the angle between faces is less than the smooth value.

Component Signature

Props

name
type
required
default
description

font
Font | string
yes
Either a loaded font or a path to a font file.

text
string
yes
The text to display.

bevelEnabled
boolean
no
false

bevelOffset
number
no
0

bevelSegments
number
no
3

bevelSize
number
no
8

bevelThickness
number
no
10

curveSegments
number
no
12

depth
number
no
1

extrudePath
Curve<Vector3>
no

height
number
no
50

size
number
no
100

smooth
number
no
0
Smooth all edges where the angle between faces is less than value

steps
number
no
1

UVGenerator
UVGenerator
no