charming_fork_zephyr/renderer/
wasm_renderer.rs

1use crate::{theme::Theme, Chart, EchartsError};
2use serde::Serialize;
3use serde_wasm_bindgen::to_value;
4use wasm_bindgen::prelude::*;
5use wasm_bindgen::JsValue;
6
7pub struct WasmRenderer {
8    theme: Theme,
9    width: u32,
10    height: u32,
11}
12
13impl WasmRenderer {
14    pub fn new(width: u32, height: u32) -> Self {
15        Self {
16            theme: Theme::Default,
17            width,
18            height,
19        }
20    }
21
22    pub fn theme(mut self, theme: Theme) -> Self {
23        self.theme = theme;
24        self
25    }
26
27    pub fn render(&self, id: &str, chart: &Chart) -> Result<Echarts, EchartsError> {
28        let window = web_sys::window().ok_or(EchartsError::WasmError(
29            "no `window` object found".to_string(),
30        ))?;
31        let document = window.document().ok_or(EchartsError::WasmError(
32            "no `document` object found".to_string(),
33        ))?;
34        let element = document
35            .get_element_by_id(id)
36            .ok_or(EchartsError::WasmError(format!(
37                "no element with id `{}` found",
38                id
39            )))?;
40        let echarts = init(
41            &element,
42            self.theme.to_str().0,
43            to_value(&ChartSize {
44                width: self.width,
45                height: self.height,
46            })
47            .unwrap(),
48        );
49        echarts.set_option(to_value(chart).unwrap());
50
51        Ok(echarts)
52    }
53
54    /// Resizes a chart with options specified in [`ChartResize`]
55    pub fn resize_chart(echarts: &Echarts, chart_size: ChartResize) {
56        echarts
57            .resize(to_value(&chart_size).expect("could not convert resize options to `JsValue`"));
58    }
59
60    pub fn update(echarts: &Echarts, chart: &Chart) {
61        echarts.set_option(to_value(chart).unwrap());
62    }
63}
64
65#[derive(Serialize)]
66struct ChartSize {
67    width: u32,
68    height: u32,
69}
70
71#[derive(Serialize)]
72pub struct ChartResize {
73    /// New width in px
74    width: u32,
75    /// New height in px
76    height: u32,
77    /// If true, emits events on resize
78    silent: bool,
79    /// Resize animation options
80    animation: Option<Animation>,
81}
82
83#[derive(Serialize)]
84pub struct Animation {
85    /// duration of the animation
86    pub duration: u32,
87    /// easing function used for the animation
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub easing: Option<Easing>,
90}
91
92/// available easing functions in echarts
93#[derive(Clone, Debug, Default, Serialize)]
94#[serde(rename_all = "camelCase")]
95pub enum Easing {
96    #[default]
97    Linear,
98    QuadraticIn,
99    QuadraticOut,
100    QuadraticInOut,
101    CubicIn,
102    CubicOut,
103    CubicInOut,
104    QuarticIn,
105    QuarticOut,
106    QuarticInOut,
107    QuinticIn,
108    QuinticOut,
109    QuinticInOut,
110    SinusoidalIn,
111    SinusoidalOut,
112    SinusoidalInOut,
113    ExponentialIn,
114    ExponentialOut,
115    ExponentialInOut,
116    CircularIn,
117    CircularOut,
118    CircularInOut,
119    ElasticIn,
120    ElasticOut,
121    ElasticInOut,
122    BackIn,
123    BackOut,
124    BackInOut,
125    BounceIn,
126    BounceOut,
127    BounceInOut,
128}
129
130impl Default for Animation {
131    fn default() -> Self {
132        Self {
133            duration: 100,
134            easing: Some(Easing::default()),
135        }
136    }
137}
138
139impl Animation {
140    pub fn new(duration: u32, easing: Option<Easing>) -> Self {
141        Self {
142            duration,
143            easing: easing.or_else(|| Some(Easing::default())),
144        }
145    }
146}
147
148#[wasm_bindgen]
149extern "C" {
150    #[wasm_bindgen(js_name = echarts)]
151    pub type Echarts;
152
153    #[wasm_bindgen(js_namespace = echarts, js_name = init)]
154    fn init(id: &web_sys::Element, theme: &str, size: JsValue) -> Echarts;
155
156    #[wasm_bindgen(method, js_name = "setOption")]
157    fn set_option(this: &Echarts, option: JsValue);
158
159    #[wasm_bindgen(method, js_name = "resize")]
160    pub fn resize(this: &Echarts, opts: JsValue);
161}