egui Drag Values: Speed, Range & Formatting | Rust GUI Ep 20
Video: egui Drag Values: Speed, Range & Formatting | Rust GUI Ep 20 by Taught by Celeste AI - AI Coding Coach
Watch full page →egui Drag Values: Speed, Range & Formatting | Rust GUI Ep 20
In this tutorial, you will learn how to build a transform editor using egui's draggable number controls. We explore the DragValue widget with customizable speed, clamped ranges, and formatted display using prefixes and suffixes, alongside interactive canvas dragging for position, rotation, and scale adjustments.
Code
use egui::{DragValue, Sense, Color32, Pos2, Rect, Rgba};
struct Transform {
position: [f32; 2],
rotation: f32,
scale: f32,
}
impl Default for Transform {
fn default() -> Self {
Self {
position: [0.0, 0.0],
rotation: 0.0,
scale: 1.0,
}
}
}
fn ui_transform_editor(ui: &mut egui::Ui, transform: &mut Transform) {
ui.vertical(|ui| {
// Draggable position X with speed and range clamping
ui.label("Position X");
DragValue::new(&mut transform.position[0])
.speed(0.5) // slower drag speed for precision
.range(-100.0..=100.0) // clamp within -100 to 100
.prefix("X: ")
.ui(ui);
// Draggable position Y
ui.label("Position Y");
DragValue::new(&mut transform.position[1])
.speed(0.5)
.range(-100.0..=100.0)
.prefix("Y: ")
.ui(ui);
// Rotation with degree suffix and clamped range
ui.label("Rotation");
DragValue::new(&mut transform.rotation)
.speed(1.0)
.range(0.0..=360.0)
.suffix("°")
.ui(ui);
// Scale with prefix and limited range
ui.label("Scale");
DragValue::new(&mut transform.scale)
.speed(0.1)
.range(0.1..=10.0)
.prefix("x")
.ui(ui);
});
}
fn ui_canvas(ui: &mut egui::Ui, transform: &mut Transform) {
let (rect, response) = ui.allocate_exact_size([300.0, 300.0].into(), Sense::click_and_drag());
if response.dragged_by(egui::PointerButton::Primary) {
let delta = response.drag_delta();
transform.position[0] += delta.x;
transform.position[1] += delta.y;
}
if response.dragged_by(egui::PointerButton::Secondary) {
let delta = response.drag_delta();
transform.rotation += delta.x * 0.5;
transform.scale += delta.y * 0.01;
transform.scale = transform.scale.clamp(0.1, 10.0);
}
// Draw a rotated rectangle representing the transform
let center = rect.center();
let rect_size = egui::vec2(100.0 * transform.scale, 50.0 * transform.scale);
let rect = Rect::from_center_size(center + egui::vec2(transform.position[0], transform.position[1]), rect_size);
let color = Rgba::from_rgb(0.2, 0.6, 0.9).to_srgba();
let painter = ui.painter();
painter.rect(
rect,
5.0,
color,
egui::Stroke::new(2.0, Color32::BLACK),
);
// Rotation visualization (simple line)
let angle = transform.rotation.to_radians();
let line_start = center + egui::vec2(transform.position[0], transform.position[1]);
let line_end = line_start + egui::vec2(angle.cos(), angle.sin()) * 50.0;
painter.line_segment([line_start, line_end], egui::Stroke::new(3.0, Color32::RED));
}
Key Points
- Use
DragValue::new()to create draggable numeric inputs with customizable speed and range. - Apply
.speed()to adjust how fast values change when dragged for better precision or responsiveness. - Clamp values using
.range()to restrict input within desired bounds. - Format displayed values with
.prefix()and.suffix()for clearer UI, such as adding units. - Enable interactive canvas dragging with
Sense::click_and_drag()and detect button-specific drags usingresponse.dragged_by().