A node of your own: an animated gauge

explainer

The brief. Write a gauge node of your own with #[derive(Node)] and Draw, then fill three of them in a row to different values.

Open in the playground Source on GitHub

What it uses

The code

examples/src/gauge.rs in oxframe-sdk, for oxframe 0.20.2. In the playground it compiles in the browser and you can change it.

//! A node of your own: a gauge that draws an arc with `DrawCtx` and
//! animates its value like any built-in node.

use oxframe::prelude::*;

/// A dial from 0 to 1.
#[derive(Node)]
pub struct Gauge {
    /// 0 is empty, 1 is full.
    #[signal]
    value: f64,
    /// Diameter in pixels.
    #[signal]
    size: f64,
}

impl Draw for Gauge {
    fn draw(&self, ctx: &mut DrawCtx) {
        let r = self.size / 2.0 - 12.0;
        ctx.arc((0.0, 0.0), r, 135.0, 270.0).stroke(Surface, 18.0);
        ctx.arc((0.0, 0.0), r, 135.0, 270.0 * self.value.clamp(0.0, 1.0))
            .stroke(Accent, 18.0);
    }

    fn size(&self) -> (f64, f64) {
        (self.size, self.size)
    }
}

#[oxframe::scene]
pub async fn dials(view: View) {
    let row = view.add(Layout::new().gap(80.0));
    let gauges: Vec<GaugeHandle> = [0.35, 0.8, 0.55]
        .into_iter()
        .map(|_| row.add(Gauge::new().size(260.0)))
        .collect();
    view.add(
        Txt::new()
            .text("A node of your own")
            .h1()
            .to_edge(Edge::Top),
    );
    stagger(0.2, [0.35, 0.8, 0.55].into_iter().enumerate(), |(i, v)| {
        gauges[i].value().to(v, 1.0)
    })
    .await;
    wait_for(0.5).await;
}

pub fn project() -> Project {
    Project::new("gauge").scene(dials())
}

More examples