From 61d3bc52b806da56c9d8df8bd5600fe5570b1f7a Mon Sep 17 00:00:00 2001 From: Maciej Ziarkowski Date: Sun, 17 Nov 2024 00:38:31 +0100 Subject: [PATCH] feat: Use `TTFLoader` in `useFont` for non-JSON files (#2095) * Fix useFont example in docs * Remove unused imports from Text3D * Use TTFLoader in useFont * Update documentation for Text3D * Add story for Text3D using TTFLoader * ttf font --------- Co-authored-by: Antoine BERNIER --- .storybook/public/fonts/lemon-round.ttf | Bin 0 -> 264752 bytes .storybook/stories/Text3D.stories.tsx | 14 ++++++++-- docs/abstractions/text3d.mdx | 2 ++ docs/loaders/use-font.mdx | 12 +++++++-- src/core/Text3D.tsx | 7 +++-- src/core/useFont.tsx | 33 +++++++++++++++++++----- 6 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 .storybook/public/fonts/lemon-round.ttf diff --git a/.storybook/public/fonts/lemon-round.ttf b/.storybook/public/fonts/lemon-round.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fe5a98e0840040965f9ee67a37eafb215f1dee0a GIT binary patch literal 264752 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 literal 0 HcmV?d00001 diff --git a/.storybook/stories/Text3D.stories.tsx b/.storybook/stories/Text3D.stories.tsx index d7b2543c1..e0e2d7645 100644 --- a/.storybook/stories/Text3D.stories.tsx +++ b/.storybook/stories/Text3D.stories.tsx @@ -16,6 +16,10 @@ export default { ), ], + args: { + bevelEnabled: true, + bevelSize: 0.05, + }, } satisfies Meta type Story = StoryObj @@ -36,9 +40,15 @@ function Text3DScene(props: React.ComponentProps) { export const Text3DSt = { args: { font: '/fonts/helvetiker_regular.typeface.json', - bevelEnabled: true, - bevelSize: 0.05, }, render: (args) => , name: 'Default', } satisfies Story + +export const Text3DTtfSt = { + args: { + font: '/fonts/lemon-round.ttf', + }, + render: (args) => , + name: 'TTF', +} satisfies Story diff --git a/docs/abstractions/text3d.mdx b/docs/abstractions/text3d.mdx index 2e2a18116..dc03fcc39 100644 --- a/docs/abstractions/text3d.mdx +++ b/docs/abstractions/text3d.mdx @@ -15,6 +15,8 @@ Render 3D text using ThreeJS's `TextGeometry`. Text3D will suspend while loading the font data. Text3D requires fonts in JSON format generated through [typeface.json](http://gero3.github.io/facetype.js), either as a path to a JSON file or a JSON object. If you face display issues try checking "Reverse font direction" in the typeface tool. +Alternatively, the path can point to a font file of a type supported by [opentype.js](https://github.com/opentypejs/opentype.js) (for example OTF or TTF), in which case the conversion to the JSON format will be done automatically at load time. + ```jsx Hello world! diff --git a/docs/loaders/use-font.mdx b/docs/loaders/use-font.mdx index 2d45a1cd8..a983beaed 100644 --- a/docs/loaders/use-font.mdx +++ b/docs/loaders/use-font.mdx @@ -3,11 +3,11 @@ title: useFont sourcecode: src/core/useFont.tsx --- -Uses THREE.FontLoader to load a font and returns a `THREE.Font` object. It also accepts a JSON object as a parameter. You can use this to preload or share a font across multiple components. +Uses `THREE.FontLoader` to load a font and returns a `THREE.Font` object. It also accepts a JSON object as a parameter. You can use this to preload or share a font across multiple components. ```jsx const font = useFont('/fonts/helvetiker_regular.typeface.json') -return +return ``` In order to preload you do this: @@ -15,3 +15,11 @@ In order to preload you do this: ```jsx useFont.preload('/fonts/helvetiker_regular.typeface.json') ``` + +If the response from the URL is not a JSON, `THREE.TTFLoader` is used to try parsing the response as a standard font file. +However, keep in mind that the on-the-fly conversion to the JSON format will impact the loading time. + +```jsx +const font = useFont('/fonts/helvetiker_regular.ttf') +return +``` diff --git a/src/core/Text3D.tsx b/src/core/Text3D.tsx index 1aa809b9a..777654bb7 100644 --- a/src/core/Text3D.tsx +++ b/src/core/Text3D.tsx @@ -2,9 +2,8 @@ import * as React from 'react' import * as THREE from 'three' import { extend, MeshProps, Node } from '@react-three/fiber' import { useMemo } from 'react' -import { suspend } from 'suspend-react' -import { mergeVertices, TextGeometry, TextGeometryParameters, FontLoader } from 'three-stdlib' -import { useFont, FontData } from './useFont' +import { mergeVertices, TextGeometry, TextGeometryParameters } from 'three-stdlib' +import { useFont } from './useFont' import { ForwardRefComponent } from '../helpers/ts-utils' declare global { @@ -16,7 +15,7 @@ declare global { } type Text3DProps = { - font: FontData | string + font: Parameters[0] bevelSegments?: number smooth?: number } & Omit & diff --git a/src/core/useFont.tsx b/src/core/useFont.tsx index 5e5200afc..4d1e373af 100644 --- a/src/core/useFont.tsx +++ b/src/core/useFont.tsx @@ -1,4 +1,4 @@ -import { FontLoader } from 'three-stdlib' +import { FontLoader, TTFLoader } from 'three-stdlib' import { suspend, preload, clear } from 'suspend-react' export type Glyph = { @@ -22,10 +22,7 @@ export type FontData = { type FontInput = string | FontData let fontLoader: FontLoader | null = null - -async function loadFontData(font: FontInput): Promise { - return typeof font === 'string' ? await (await fetch(font)).json() : font -} +let ttfLoader: TTFLoader | null = null function parseFontData(fontData: FontData) { if (!fontLoader) { @@ -34,9 +31,31 @@ function parseFontData(fontData: FontData) { return fontLoader.parse(fontData) } +function parseTtfArrayBuffer(ttfData: ArrayBuffer) { + if (!ttfLoader) { + ttfLoader = new TTFLoader() + } + return ttfLoader.parse(ttfData) as FontData +} + +async function loadFontData(font: FontInput) { + if (typeof font === 'string') { + const res = await fetch(font) + + if (res.headers.get('Content-Type')?.includes('application/json')) { + return (await res.json()) as FontData + } else { + const arrayBuffer = await res.arrayBuffer() + return parseTtfArrayBuffer(arrayBuffer) + } + } else { + return font + } +} + async function loader(font: FontInput) { - const data = await loadFontData(font) - return parseFontData(data) + const fontData = await loadFontData(font) + return parseFontData(fontData) } export function useFont(font: FontInput) {