Time scale and whitespace
The time scale places bars horizontally. Logical coordinates address this chart’s slots; UTC coordinates address instants that other charts can share. The scene uses the first chart’s 120 fixed one-minute bars.
Try fitting, scrolling and ranges
Section titled “Try fitting, scrolling and ranges”Use Fit history, Back 30 bars, Live edge and Reset time. Compare
Logical 20..59 with UTC minutes 20..59, then select Future space to
extend past the last bar. Readouts describe the last layout; they also update
when you pan or zoom directly.
Call the scene’s show(ui, &mut chart) before chart.show(ui) on each frame.
Fit and scroll, set a logical or UTC range, then leave future whitespace.
The interactive example needs JavaScript and WebAssembly. You can still use the chart setup alongside it.
use chrono::TimeDelta;use eframe::egui;use egui_charts::{ Chart, model::LogicalRange, widget::{SeriesId, VisibleTimeRange},};
/// Fit, scroll and address the same history in logical or UTC coordinates.pub fn show(ui: &mut egui::Ui, chart: &mut Chart) { // Range setters use the plot width from the last show, including after a resize. let ready = chart.time_scale_size().x > 0.0; ui.add_enabled_ui(ready, |ui| { ui.horizontal_wrapped(|ui| { if ui.button("Fit history").clicked() { chart.fit_content(); } if ui.button("Back 30 bars").clicked() { chart.scroll_to_position(-30.0, true); } if ui.button("Live edge").clicked() { chart.scroll_to_real_time(true); } if ui.button("Reset time").clicked() { chart.reset_time_scale(); } }); ui.horizontal_wrapped(|ui| { if ui.button("Logical 20..59").clicked() { chart.set_visible_logical_range(LogicalRange { left: 20.0, right: 59.0, }); } if ui.button("UTC minutes 20..59").clicked() { let start = chart.bars(SeriesId::MAIN)[0].time; chart.apply_synced_time_range(VisibleTimeRange { from: start + TimeDelta::minutes(20), to: start + TimeDelta::minutes(59), }); } if ui.button("Future space").clicked() { chart.set_visible_logical_range(LogicalRange { left: 80.0, right: 139.0, }); } }); }); if ready { if let Some(range) = chart.visible_logical_range() { ui.label(format!("Logical: {:.2} .. {:.2}", range.left, range.right)); } if let Some(range) = chart.visible_time_range() { ui.label(format!( "UTC: {} .. {}", range.from.format("%F %T"), range.to.format("%F %T") )); } if let Some(x) = chart.index_to_x(30.0) { let time = chart.index_to_time(30.0).unwrap(); let index = chart.time_to_index(time).unwrap(); ui.label(format!( "Index {index:.0} = {} UTC; x = {x:.1} pt", time.format("%T") )); } } else { ui.label("Waiting for the first plot layout."); }}Fit and scroll
Section titled “Fit and scroll”fit_content
fits the stored history and keeps the configured right margin.
scroll_to_position
positions the latest bar relative to the right edge in bars: positive positions
leave space on the right, negative positions scroll into history.
scroll_to_real_time
returns to the live edge while keeping zoom; it is a one-time scroll. Its
animated flag, also used by scroll_to_position, animates the move. These
scenes use fixed data; a host supplies historical and streaming updates.
reset_time_scale
restores the configured spacing and right offset. It leaves the price ranges
alone. reset_chart_view
also returns every pane’s price scales to autoscale.
Logical indices and UTC instants
Section titled “Logical indices and UTC instants”visible_logical_range
returns a LogicalRange.
Index 0 is the oldest slot in this chart; bounds can be fractional or outside
the data. A range spans right - left + 1 bar widths, so 20..59 spans 40.
set_visible_logical_range
sets spacing and scroll together. It returns false for empty data, non-finite
bounds or reversed bounds, keeping the view unchanged. Spacing and edge limits
still apply. Logical indices depend on the chart’s history and interval; do not
copy them between charts with different slots.
visible_time_range
returns a VisibleTimeRange
in UTC, including whitespace. Use
apply_synced_time_range
to fit those instants to another chart’s width. Check its boolean result:
empty data, invalid or wholly disjoint ranges, and endpoints mapping to one
element are rejected. Its maximum spacing is the configured limit, or 50 points
when unlimited, so very short spans may be centred rather than filling the plot.
index_to_time
and time_to_index
convert between fractional slots and UTC. Times between bars are interpolated;
outside the history they are extrapolated using the interval or observed edge
spacing. Calendar month and year intervals follow calendar stepping, as detailed
in the method documentation. Display time zones affect labels, while the data
and shared time ranges remain UTC.
Leave future whitespace
Section titled “Leave future whitespace”The last sample bar has logical index 119. The scene’s 80..139 range leaves
20 logical slots beyond it without inventing future OHLC values. To include a
known empty timestamp in supplied history, use
Bar::whitespace.
TimeScaleOptions
is available through
ChartOptions::time_scale.
Edit a copy from chart_options() and apply it with
set_chart_options.
right_offsetsets live-edge space in bars;right_offset_pixelstakes priority when present.bar_spacing,min_bar_spacingandmax_bar_spacingcontrol zoom and constrain fitting.fix_left_edgeandfix_right_edgeconstrain scrolling, including requested whitespace.lock_visible_time_range_on_resizekeeps the visible time range when the chart size changes.
Wait for plot geometry
Section titled “Wait for plot geometry”Call Chart::show
once at the intended size before fitting a range or converting screen positions.
The range setters use the last drawn plot width; after resizing, show again
before applying a width-dependent range. The scene enables its buttons once
time_scale_size
reports a positive width.
index_to_x
and x_to_index
use screen points in the chart’s egui Ui, with x at the bar centre. They
return None before the first layout. For separate charts, choose one source
and forward only its changed UTC range and
hover_time
to set_synced_crosshair_time.
The builder guide and
synchronized charts example
show that integration.