Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ui/text/letter_spacing.rs
30635 views
1
//! This example demonstrates the `LetterSpacing` component in Bevy's text system.
2
//!
3
//! Use the left and right arrow keys to adjust the letter spacing of the text.
4
5
use bevy::prelude::*;
6
use bevy::text::{LetterSpacing, RemSize};
7
8
#[derive(Component)]
9
struct LetterSpacingLabel;
10
11
#[derive(Component)]
12
struct AnimatedLetterSpacing;
13
14
#[derive(Resource, Default)]
15
enum SpacingMode {
16
#[default]
17
Px,
18
Rem,
19
}
20
21
fn main() {
22
App::new()
23
.add_plugins(DefaultPlugins)
24
.init_resource::<SpacingMode>()
25
.add_systems(Startup, setup)
26
.add_systems(Update, (update_letter_spacing, toggle_mode))
27
.run();
28
}
29
30
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
31
commands.spawn(Camera2d);
32
33
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
34
35
commands
36
.spawn(Node {
37
width: percent(100),
38
height: percent(100),
39
..default()
40
})
41
.with_children(|parent| {
42
parent
43
.spawn(Node {
44
width: percent(100),
45
height: percent(100),
46
align_items: AlignItems::Center,
47
padding: UiRect::axes(vw(5), vh(10)),
48
row_gap: vh(6),
49
flex_direction: FlexDirection::Column,
50
..default()
51
})
52
.with_children(|parent| {
53
parent.spawn((
54
Text::new("HELLO"),
55
Underline,
56
TextFont {
57
font: font.clone().into(),
58
font_size: FontSize::Vh(6.0),
59
..default()
60
},
61
Node {
62
padding: vh(2).bottom(),
63
..default()
64
},
65
));
66
67
// Left justified
68
parent
69
.spawn(Node {
70
flex_direction: FlexDirection::Column,
71
width: percent(100.0),
72
..default()
73
})
74
.with_children(|parent| {
75
parent.spawn((
76
Text::new("Justify::Left"),
77
TextFont {
78
font: font.clone().into(),
79
font_size: FontSize::Vh(2.0),
80
..default()
81
},
82
));
83
parent.spawn((
84
Text::new("letter spacing"),
85
AnimatedLetterSpacing,
86
TextLayout::justify(Justify::Left),
87
TextFont {
88
font: font.clone().into(),
89
font_size: FontSize::Vh(6.0),
90
..default()
91
},
92
Node {
93
width: percent(100.0),
94
..default()
95
},
96
// Custom `LetterSpacing` can be added to any text entity as a component
97
LetterSpacing::Px(0.0),
98
));
99
});
100
101
// Center justified
102
parent
103
.spawn(Node {
104
flex_direction: FlexDirection::Column,
105
width: percent(100.0),
106
..default()
107
})
108
.with_children(|parent| {
109
parent.spawn((
110
Text::new("Justify::Center"),
111
TextFont {
112
font: font.clone().into(),
113
font_size: FontSize::Vh(2.0),
114
..default()
115
},
116
));
117
parent.spawn((
118
Text::new("letter spacing"),
119
AnimatedLetterSpacing,
120
TextLayout::justify(Justify::Center),
121
TextFont {
122
font: font.clone().into(),
123
font_size: FontSize::Vh(6.0),
124
..default()
125
},
126
Node {
127
width: percent(100.0),
128
..default()
129
},
130
// Custom `LetterSpacing` can be added to any text entity as a component
131
LetterSpacing::Px(0.0),
132
));
133
});
134
135
// Right justified
136
parent
137
.spawn(Node {
138
flex_direction: FlexDirection::Column,
139
width: percent(100.0),
140
..default()
141
})
142
.with_children(|parent| {
143
parent.spawn((
144
Text::new("Justify::Right"),
145
TextFont {
146
font: font.clone().into(),
147
font_size: FontSize::Vh(2.0),
148
..default()
149
},
150
));
151
parent.spawn((
152
Text::new("letter spacing"),
153
AnimatedLetterSpacing,
154
TextLayout::justify(Justify::Right),
155
TextFont {
156
font: font.clone().into(),
157
font_size: FontSize::Vh(6.0),
158
..default()
159
},
160
Node {
161
width: percent(100.0),
162
..default()
163
},
164
// Custom `LetterSpacing` can be added to any text entity as a component
165
LetterSpacing::Px(0.0),
166
));
167
});
168
});
169
170
parent.spawn((
171
Text::new("LetterSpacing::Px(0.0)"),
172
LetterSpacingLabel,
173
TextFont {
174
font: font.clone().into(),
175
font_size: FontSize::Vh(3.0),
176
..default()
177
},
178
Node {
179
position_type: PositionType::Absolute,
180
bottom: vh(2.0),
181
left: vw(2.0),
182
..default()
183
},
184
));
185
186
parent.spawn((
187
Text::new("← → to adjust Space to toggle Px / Rem"),
188
TextFont {
189
font: font.clone().into(),
190
font_size: FontSize::Vh(2.5),
191
..default()
192
},
193
Node {
194
position_type: PositionType::Absolute,
195
bottom: vh(2.0),
196
right: vw(2.0),
197
..default()
198
},
199
));
200
});
201
}
202
203
fn toggle_mode(
204
keyboard: Res<ButtonInput<KeyCode>>,
205
mut mode: ResMut<SpacingMode>,
206
rem_size: Res<RemSize>,
207
mut query: Query<&mut LetterSpacing, With<AnimatedLetterSpacing>>,
208
mut label_query: Query<&mut Text, With<LetterSpacingLabel>>,
209
) {
210
if !keyboard.just_pressed(KeyCode::Space) {
211
return;
212
}
213
214
for mut spacing in &mut query {
215
let new_spacing = match *spacing {
216
LetterSpacing::Px(v) => {
217
*mode = SpacingMode::Rem;
218
LetterSpacing::Rem(v / rem_size.0)
219
}
220
LetterSpacing::Rem(v) => {
221
*mode = SpacingMode::Px;
222
LetterSpacing::Px(v * rem_size.0)
223
}
224
};
225
*spacing = new_spacing;
226
}
227
228
for mut text in &mut label_query {
229
match *mode {
230
SpacingMode::Px => {
231
if let Some(LetterSpacing::Px(v)) = query.iter().next().copied() {
232
text.0 = format!("LetterSpacing::Px({:.1})", v);
233
}
234
}
235
SpacingMode::Rem => {
236
if let Some(LetterSpacing::Rem(v)) = query.iter().next().copied() {
237
text.0 = format!("LetterSpacing::Rem({:.2})", v);
238
}
239
}
240
}
241
}
242
}
243
244
fn update_letter_spacing(
245
keyboard: Res<ButtonInput<KeyCode>>,
246
mut query: Query<&mut LetterSpacing, With<AnimatedLetterSpacing>>,
247
mut label_query: Query<&mut Text, With<LetterSpacingLabel>>,
248
) {
249
let delta = if keyboard.pressed(KeyCode::ArrowRight) {
250
0.5
251
} else if keyboard.pressed(KeyCode::ArrowLeft) {
252
-0.5
253
} else {
254
return;
255
};
256
257
for mut spacing in &mut query {
258
match *spacing {
259
LetterSpacing::Px(current) => {
260
let new_value = (current + delta).clamp(-100.0, 100.0);
261
*spacing = LetterSpacing::Px(new_value);
262
for mut text in &mut label_query {
263
text.0 = format!("LetterSpacing::Px({:.1})", new_value);
264
}
265
}
266
LetterSpacing::Rem(current) => {
267
let new_value = (current + delta * 0.1).clamp(-10.0, 10.0);
268
*spacing = LetterSpacing::Rem(new_value);
269
for mut text in &mut label_query {
270
text.0 = format!("LetterSpacing::Rem({:.2})", new_value);
271
}
272
}
273
}
274
}
275
}
276
277