Multi axes
Two y axes with independent ranges on one plot. Temperature (0..30) and
pressure (~1000 hPa) would be unreadable sharing a single axis, so pressure
gets its own right-hand y axis. Three calls do it: setup_axis enables the
second axis, setup_axis_limits ranges it, and set_axis routes the next
items onto it.
plot(CHART, (title = "weather", size = float2(-1.0f, 600.0f), flags = ImPlotFlags.None)) {
setup_axes("hour", "temp (C)")
setup_axis(ImAxis.Y2, "pressure (hPa)", ImPlotAxisFlags.AuxDefault) // enable Y2
setup_axis_limits(ImAxis.Y1, 0.0lf, 30.0lf)
setup_axis_limits(ImAxis.Y2, 950.0lf, 1050.0lf)
plot_line("temp", g_temp) // default Y1
set_axis(ImAxis.Y2) // route what follows to Y2
plot_line("pressure", g_press)
}
Source: examples/tutorial/multi_axes.das.
1options gen2
2
3require imgui/imgui_harness
4require imgui/imgui_containers_builtin
5require imgui/imgui_widgets_builtin
6require imgui/imgui_implot_boost_v2
7require implot
8require math
9
10// =============================================================================
11// TUTORIAL: multi_axes — two y axes with different scales on one plot.
12//
13// setup_axis(ImAxis.Y2, label, ImPlotAxisFlags.AuxDefault) — enable a 2nd y axis.
14// setup_axis_limits(ImAxis.Y2, ...) — range it independently.
15// set_axis(ImAxis.Y2) — route the NEXT items to it.
16//
17// Temperature (0..30) lives on the left Y1; pressure (~1000 hPa) on the right Y2 —
18// wildly different ranges that would be unreadable sharing one axis.
19//
20// STANDALONE: daslang.exe modules/dasImguiImplot/examples/tutorial/multi_axes.das
21// LIVE: daslang-live modules/dasImguiImplot/examples/tutorial/multi_axes.das
22// =============================================================================
23
24let N = 100
25
26var g_ctx : ImPlotContext?
27var g_temp : array<double> // small range, Y1
28var g_press : array<double> // large range, Y2
29
30[export]
31def init() {
32 harness_init("dasImguiImplot — multi_axes", 1100, 720)
33 g_ctx = implot::CreateContext()
34 g_temp <- [for (i in range(N)); 17.0lf + 6.0lf * double(sin(float(i) * 0.10f))]
35 g_press <- [for (i in range(N)); 1000.0lf + 30.0lf * double(cos(float(i) * 0.07f))]
36}
37
38[export]
39def update() {
40 if (!harness_begin_frame()) return
41 harness_new_frame()
42
43 SetNextWindowPos(float2(20.0, 20.0), ImGuiCond.Always)
44 SetNextWindowSize(float2(1060.0, 680.0), ImGuiCond.Always)
45 window(PLOT_WIN, (text = "multi axes", closable = false,
46 flags = ImGuiWindowFlags.None)) {
47 text("Temperature on Y1 (left), pressure on Y2 (right). set_axis routes an item to Y2.")
48 plot(CHART, (title = "weather", size = float2(-1.0f, 600.0f),
49 flags = ImPlotFlags.None)) {
50 setup_axes("hour", "temp (C)")
51 setup_axis(ImAxis.Y2, "pressure (hPa)", ImPlotAxisFlags.AuxDefault)
52 setup_axis_limits(ImAxis.X1, 0.0lf, double(N))
53 setup_axis_limits(ImAxis.Y1, 0.0lf, 30.0lf)
54 setup_axis_limits(ImAxis.Y2, 950.0lf, 1050.0lf)
55 // Temperature on the default Y1.
56 next_line_style(float4(1.00f, 0.55f, 0.20f, 1.00f), 2.0f)
57 plot_line("temp", g_temp)
58 // Route the next item to Y2, then plot pressure against it.
59 set_axis(ImAxis.Y2)
60 next_line_style(float4(0.35f, 0.75f, 1.00f, 1.00f), 2.0f)
61 plot_line("pressure", g_press)
62 }
63 }
64
65 harness_end_frame()
66}
67
68[export]
69def shutdown() {
70 if (g_ctx != null) {
71 DestroyContext(g_ctx)
72 }
73 harness_shutdown()
74}
75
76[export]
77def main() {
78 init()
79 while (!exit_requested()) {
80 update()
81 }
82 shutdown()
83}
Walkthrough
Enabling a second axis
setup_axis(ImAxis.Y2, label, ImPlotAxisFlags.AuxDefault) turns on the second
y axis with a sensible default style (auto-fit, opposite side). ImPlot supports up
to three of each — Y1 / Y2 / Y3 and likewise for x. Each is ranged
independently with setup_axis_limits(axis, …).
Routing items to an axis
Items go on whichever axis pair is current; Y1 is the default. set_axis(axis)
switches the current y axis so every item after it draws against that axis —
here, plot_line("pressure", …) lands on Y2. The two-axis form
set_axes(x_axis, y_axis) switches both at once. Because the snapshot captures
GetPlotLimits(X1, Y1), the test_multi_axes regression asserts Y1 stays
[0,30] — confirming pressure’s [950,1050] lives on a genuinely separate axis.
Panning one axis
Each axis can be panned on its own: left-drag on an axis’ tick-label gutter — the strip just outside the data area — and only that axis moves. In the walkthrough, dragging the left gutter pans temperature while pressure holds, then dragging the right gutter pans pressure while temperature holds. This is the multi-axis payoff over a plain plot-body drag, which pans every axis at once. The recording drives both drags with real synthetic input and asserts the dragged axis’ range moved while the other stayed put, so a no-op — or a drag that bled across to the other axis — fails it.