How does one convert a downloaded google font from ttf to json for use with ThreeJS FontLoader / TextGeometry?
import LatoFont from '../assets/fonts/lato-bold.json'
const loader = new FontLoader();
const font = loader.parse(LatoFont);
loader.load(font, font => {
const textGeo = new TextGeometry("Krypton", {
font: font,
size: 200,
height: 50,
curveSegments: 12,
bevelEnabled: false,
bevelThickness: 0.5,
bevelSize: 0.3,
bevelOffset: 0,
bevelSegments: 5,
})
const materials = [
new THREE.MeshPhongMaterial({ color: 0x00ff00, flatShading: true }), // front
new THREE.MeshPhongMaterial({ color: 0x00ff00 }) // side
]
const textMesh = new THREE.Mesh(textGeo, materials);
textGeo.computeBoundingBox();
const centerOffset = - 0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
textMesh.position.x = centerOffset;
textMesh.position.y = 100;
textMesh.position.z = 0;
textMesh.rotation.x = 0;
textMesh.rotation.y = Math.PI * 2;
group.add(textMesh);
})
Using a popular online convertor I am getting:
Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
UPDATE:
I updated my vite config to have the static directory. But when I build the library and use it in another project the font still has loading issues.
const path = require('path')
const { defineConfig } = require('vite')
module.exports = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'lib/main.ts'),
name: 'logo-threejs',
fileName: (format) => `logo-threejs.${format}.js`
}
},
publicDir: './static',
assetsInclude: ['**/*.typeface.json'],
});
Project Structure:
I assume that you checked all troubleshooting like path, imports, converting font, json structure…
Using a popular online convertor I am getting:
Quite unusually, you load this font using parsing, I rarely come across this method, maybe there is a problem there, I'm not sure.
Anyway, try this approach.
import { TextGeometry } from "https://esm.sh/three/addons/geometries/TextGeometry.js";
import { FontLoader } from "https://esm.sh/three/addons/loaders/FontLoader.js";
//…
const loader = new FontLoader();
loader.load(
'https://esm.sh/@compai/font-lato/data/typefaces/normal-900.json',
function (font) {
const textGeometry = new TextGeometry("Hiii", {
font: font,
size: 2,
height: 0.2,
});
const textMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const textMesh = new THREE.Mesh(textGeometry, textMaterial);
textMesh.position.set(-2, 0, 0);
scene.add(textMesh);
}
);
https://codepen.io/Lucas_Mas/pen/xxMoPwq
Her you have all fonts:
https://github.com/components-ai/typefaces/tree/main/packages
UPDATE 0
If I had to guess, the problem lies in the location of this font in your tree... Because if you did it like in my example and downloaded this font in ready-made json or converted it here http://gero3.github.io/facetype.js/ then there's probably something wrong with the location. As for the bundler, I use Vite
.
threejs-vite-project/
├── node_modules/
├── src/
│ ├── index.html
│ ├── app.js
│ └── style.css
├── static/
│ └── font/
│ └── latoSans.json
├── package-lock.json
├── package.json
└── vite.config.js
Ensure your vite.config.js
(if you use this one) file is correctly set to serve the static directory.
import { defineConfig } from 'vite';
export default defineConfig({
root: 'src',
build: {
outDir: '../dist'
},
publicDir: '../static'
});
And then, path should look like this:
const loader = new FontLoader();
loader.load(
'/static/font/latoSans.json',
function (font) {
const textGeometry = new TextGeometry("Hiii", {
font: font,
size: 2,
height: 0.2,
});
Then imports should look like this
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
UPDATE 1
.typeface.json
- you wrote that you downloaded this font from the packages from my link. By default, fonts from there does not have this extension.assetsInclude: ['**/*.json']
publicDir
(especially path)UPDATE 2
Try this approach
Project A1
Tree
project-Threejs-Vite
├── dist
│ ├── krypton-logo-threejs.es.js
│ ├── krypton-logo-threejs.umd.js
│ ├── lato-bold.json
├── lib
│ └── main.ts
├── node_modules
├── static
│ └── lato-bold.json
├── .gitignore
├── index.html
├── package-lock.json
├── package.json
├── README.md
├── style.css
└── tsconfig.json
Vite
const path = require('path');
const { defineConfig } = require('vite');
module.exports = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'lib/main.ts'),
name: 'logo-threejs',
fileName: (format) => `logo-threejs.${format}.js`
}
},
publicDir: './static',
assetsInclude: ['**/*.json'],
});
Project A2
Tree
project-B2
├── dist
├── lib
├── node_modules
├── public
│ └── lato-bold.json
├── src
│ └── main.js
├── .gitignore
├── index.html
├── package-lock.json
├── package.json
├── README.md
├── style.css
└── vite.config.js
Vite
import { defineConfig } from 'vite';
export default defineConfig({
publicDir: './public',
assetsInclude: ['**/*.json'],
});
Font existing…
Make SURE that folders contain this font. Because this is common problem with Vite, that for instance, static files (glb, etc.) you have to move manually.
Path Project A2
const loader = new FontLoader();
loader.load('/public/lato-bold.json', …
Absolute path
If things above didn’t help try set absolute path from public
const aPath = '/lato-bold.json';
const loader = new FontLoader();
loader.load(aPath, …
UPDATE 3
I don’t think so, that ts
has something to do, with fonts loading, more with extensions and files in general. But you never know…
Try maybe set "resolveJsonModule": true
, because default is disabled.
And BTW, what says devtools network requests, or any clue in console?