// text in shape
Text in shape
Fiber3DTextTexture.render draws a string (letters or numbers) into a texture. Assign that texture to Fiber3DStandardMaterial.map and the text appears on the shape's surface.
One mesh shows one text. A mesh takes exactly one material, and a material holds one texture, so a single mesh can't show a different text on each face. A Fiber3DBox shows the same texture on all six faces. To put different text on each face, build the shape out of separate flat Fiber3DPlane meshes, one per face, each with its own texture. The dice example below does this with six planes.
// demo
Demo
A die made of six Fiber3DPlane faces, each showing a different number rendered with Fiber3DTextTexture.
// how to use it
How to use it
One text on one shape. Render the texture (it is asynchronous, so wait for it), then use it as the map:
final texture = await Fiber3DTextTexture.render(
text: 'Hello',
fontSize: 64,
color: const Color(0xFFFFFFFF),
backgroundColor: const Color(0xFF3366FF),
);
Fiber3DMesh(
geometry: Fiber3DPlane(width: 2, height: 1),
material: Fiber3DStandardMaterial(color: 0xffffff, map: texture),
showEdges: false,
)Different text on each face. Each face is its own Fiber3DPlane (a flat square that faces +Z by default). The code renders six textures, then places six planes half a cube-width out from the center, each rotated to face outward. Wrapping them in a Fiber3DGroup lets the whole die spin as one object. A complete scene:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_fiber/flutter_fiber.dart';
void main() => runApp(const DiceShapeDemo());
class DiceShapeDemo extends StatefulWidget {
const DiceShapeDemo({super.key});
@override
State<DiceShapeDemo> createState() => _DiceShapeDemoState();
}
/// One cube face: position (half-extent already applied), a rotation
/// about x and y, and the text to show on it.
class _FaceSpec {
final double x, y, z;
final double rotX, rotY;
final String label;
const _FaceSpec(this.x, this.y, this.z, this.rotX, this.rotY, this.label);
}
class _DiceShapeDemoState extends State<DiceShapeDemo> {
static const _half = 0.9; // half of a 1.8-unit cube
static final List<_FaceSpec> _faces = [
_FaceSpec(0, 0, _half, 0, 0, '1'), // +Z (Fiber3DPlane's default facing)
_FaceSpec(_half, 0, 0, 0, pi / 2, '2'), // +X
_FaceSpec(0, _half, 0, -pi / 2, 0, '3'), // +Y
_FaceSpec(0, -_half, 0, pi / 2, 0, '4'), // -Y
_FaceSpec(-_half, 0, 0, 0, -pi / 2, '5'), // -X
_FaceSpec(0, 0, -_half, 0, pi, '6'), // -Z
];
List<Fiber3DTexture>? _textures;
@override
void initState() {
super.initState();
// Render one texture per face, then rebuild once all are ready.
Future.wait(
_faces.map(
(f) => Fiber3DTextTexture.render(
text: f.label,
fontSize: 140,
color: const Color(0xFF1A1A1A),
backgroundColor: const Color(0xFFF5F5F5),
),
),
).then((textures) {
if (!mounted) return;
setState(() => _textures = textures);
});
}
@override
Widget build(BuildContext context) {
final textures = _textures;
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('flutter_fiber: text-in-shape (dice)')),
body: Fiber3DCanvas(
backgroundColor: 0x303130,
camera: Fiber3DCamera(
position: const Fiber3DVector3(0, 0, 5),
target: const Fiber3DVector3.zero(),
),
orbitEnabled: true,
lights: const [
Fiber3DAmbientLight(color: 0xffffff, intensity: 0.6),
Fiber3DPointLight(
color: 0xffffff,
intensity: 3.0,
position: Fiber3DVector3(3, 4, 5),
),
],
children: textures == null
? const []
: [
// The group spins all six faces together as one die.
Fiber3DGroup(
onFrame: (elapsed, delta, transform) {
final t = delta.inMicroseconds / 1e6;
transform.rotation.y += t;
transform.rotation.x += t * 0.4;
},
children: [
for (var i = 0; i < _faces.length; i++)
Fiber3DMesh(
geometry: Fiber3DPlane(width: 1.8, height: 1.8),
material: Fiber3DStandardMaterial(
map: textures[i],
roughness: 0.6,
metalness: 0.0,
),
showEdges: false,
hitRadius: 1.0,
onFrame: (elapsed, delta, transform) {
final f = _faces[i];
transform.position.set(f.x, f.y, f.z);
transform.rotation.x = f.rotX;
transform.rotation.y = f.rotY;
transform.rotation.z = 0.0;
},
),
],
),
],
),
),
);
}
}// parameters
Parameters
All parameters of Fiber3DTextTexture.render:
text
default requiredThe string to draw.
fontSize
default 48Logical font size.
color
default whiteText color (a dart:ui Color).
backgroundColor
default transparentFill behind the text.
fontFamily
default nullOptional font family.
fontWeight
default FontWeight.normalWeight of the text.
textAlign
default TextAlign.centerAlignment of the text.
padding
default 16Logical padding around the text.
pixelRatio
default 2.0Rasterization scale. Higher = sharper.
// tips & limits
Tips & limits
- Render the textures before showing the mesh. In the dice example the canvas has no children until all six textures are ready.
- The texture's size follows the text plus padding. Size the surface you map it on with a matching aspect ratio (for example a
Fiber3DPlane) to avoid stretching. - Only
Fiber3DStandardMaterialaccepts textures. - Use
color: 0xffffff(the default) on the material to show the texture untinted.