GithubHelp home page GithubHelp logo

tsuitoar / egui-plotter Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gip-gip/egui-plotter

0.0 0.0 0.0 17.13 MB

Simple to use utilties for integrating plotter into egui

License: MIT License

Rust 100.00%

egui-plotter's Introduction

egui-plotter

MIT License Crates.io Documentation APE

simple to use utilties for integrating plotter into egui

3d Graph Live Demo Spiral Live Demo

Usage

This crate can be used by adding egui-plotter to the dependencies in your project's Cargo.toml.

[dependencies]
egui-plotter = "0.3.0"

It is also heavily recommended you disable feathering in your egui context, as not only does it slow things down but it causes artifacts with certain plots.

See line 24 example below to see how to disable feathering.

Features

  • timechart - Includes all the pre-made animatable charts like XyTimeData and TimeData.

Examples

Here's a simple plotter example being run on native eframe. Derived from eframe and plotters.

use eframe::egui::{self, CentralPanel, Visuals};
use egui_plotter::EguiBackend;
use plotters::prelude::*;

fn main() {
    let native_options = eframe::NativeOptions::default();
    eframe::run_native(
        "Simple Example",
        native_options,
        Box::new(|cc| Box::new(Simple::new(cc))),
    )
    .unwrap();
}

struct Simple;

impl Simple {
    fn new(cc: &eframe::CreationContext<'_>) -> Self {
        // Disable feathering as it causes artifacts
        let context = &cc.egui_ctx;

        context.tessellation_options_mut(|tess_options| {
            tess_options.feathering = false;
        });

        // Also enable light mode
        context.set_visuals(Visuals::light());

        Self
    }
}

impl eframe::App for Simple {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        CentralPanel::default().show(ctx, |ui| {
            let root = EguiBackend::new(ui).into_drawing_area();
            root.fill(&WHITE).unwrap();
            let mut chart = ChartBuilder::on(&root)
                .caption("y=x^2", ("sans-serif", 50).into_font())
                .margin(5)
                .x_label_area_size(30)
                .y_label_area_size(30)
                .build_cartesian_2d(-1f32..1f32, -0.1f32..1f32)
                .unwrap();

            chart.configure_mesh().draw().unwrap();

            chart
                .draw_series(LineSeries::new(
                    (-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)),
                    &RED,
                ))
                .unwrap()
                .label("y = x^2")
                .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));

            chart
                .configure_series_labels()
                .background_style(&WHITE.mix(0.8))
                .border_style(&BLACK)
                .draw()
                .unwrap();

            root.present().unwrap();
        });
    }
}

Charts

Alternatively, the above example can be made with a Chart type to allow easy user interactivity with your plotter charts. You can either make your own chart or use a prebuilt chart type included in the charts module.

use eframe::egui::{self, CentralPanel, Key, Visuals};
use egui_plotter::{Chart, MouseConfig};
use plotters::prelude::*;
use std::ops::Range;

fn main() {
    let native_options = eframe::NativeOptions::default();
    eframe::run_native(
        "ParaChart Example",
        native_options,
        Box::new(|cc| Box::new(ParaChart::new(cc))),
    )
    .unwrap();
}

struct ParaChart {
    chart: Chart<(Range<f32>, Range<f32>)>,
}

impl ParaChart {
    fn new(cc: &eframe::CreationContext<'_>) -> Self {
        // Disable feathering as it causes artifacts
        let context = &cc.egui_ctx;

        context.tessellation_options_mut(|tess_options| {
            tess_options.feathering = false;
        });

        // Also enable light mode
        context.set_visuals(Visuals::light());

        // We use data to adjust the range of the chart. This can be useful for
        // line plots where the X represents time and we want to play through
        // the X, but that is not what we are using it for here
        let chart = Chart::new((-3f32..3f32, -0.5f32..3f32))
            .mouse(MouseConfig::enabled())
            .builder_cb(Box::new(|area, _t, ranges| {
                // Build a chart like you would in any other plotter chart.
                // The drawing area and ranges are provided by the callback,
                // but otherwise everything else is the same.

                let (x_range, y_range) = ranges;

                let mut chart = ChartBuilder::on(area)
                    .caption("y=x^2", ("sans-serif", 50).into_font())
                    .margin(5)
                    .x_label_area_size(30)
                    .y_label_area_size(30)
                    .build_cartesian_2d(x_range.to_owned(), y_range.to_owned())
                    .unwrap();

                chart.configure_mesh().draw().unwrap();

                chart
                    .draw_series(LineSeries::new(
                        (-50 * (x_range.end as i32)..=(50 * x_range.end as i32))
                            .map(|x| x as f32 / 50.0)
                            .map(|x| (x, x * x)),
                        &RED,
                    ))
                    .unwrap()
                    .label("y = x^2")
                    .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED));

                chart
                    .configure_series_labels()
                    .background_style(WHITE.mix(0.8))
                    .border_style(BLACK)
                    .draw()
                    .unwrap();
            }));

        Self { chart }
    }
}

impl eframe::App for ParaChart {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        CentralPanel::default().show(ctx, |ui| {
            // Press 1 for the range -1..1, 2 for -2..2, 3 for -3..3
            ui.input(|input| {
                if input.key_down(Key::Num1) {
                    *self.chart
                        .get_data_mut() = (-1f32..1f32, -0.5f32..1f32);
                }
                if input.key_down(Key::Num2) {
                    *self.chart
                        .get_data_mut() = (-2f32..2f32, -0.5f32..2f32);
                }

                if input.key_down(Key::Num3) {
                    *self.chart
                        .get_data_mut() = (-3f32..3f32, -0.5f32..3f32);
                }
            });

            self.chart.draw(ui);
        });
    }
}

egui-plotter's People

Contributors

gip-gip avatar bananaturtlesandwich avatar tsuitoar avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.