dioxus_spring/
spring.rs

1use crate::controller::request_animation_frame;
2use futures::{stream, Stream};
3use interpolation::Lerp;
4use js_sys::Date;
5use std::time::Duration;
6
7/// Create a stream of interpolated values from one value to another over a [`Duration`].
8pub fn spring<V>(from: V, to: V, duration: Duration) -> impl Stream<Item = V>
9where
10    V: Lerp<Scalar = f32> + Clone + 'static,
11{
12    let mut start_cell = None;
13    stream::unfold(false, move |is_done| {
14        if start_cell.is_none() {
15            start_cell = Some(Date::now());
16        }
17        let start = start_cell.unwrap();
18
19        let from = from.clone();
20        let to = to.clone();
21        async move {
22            if is_done {
23                return None;
24            }
25
26            request_animation_frame().await;
27
28            let dt = Date::now() - start;
29            let duration_ms = duration.as_secs_f64() * 1000.;
30            if dt >= duration_ms {
31                let v = interpolation::lerp(&from, &to, &1.);
32                return Some((v, true));
33            }
34
35            let x = dt / duration_ms;
36            let v = interpolation::lerp(&from, &to, &(x as f32));
37            Some((v, false))
38        }
39    })
40}