Skip to main content

dioxus_motion/animations/
tween.rs

1//! Tween animation module
2//!
3//! Provides time-based animation with customizable easing functions.
4//! Supports duration and interpolation control for smooth animations.
5
6#[cfg(feature = "dioxus")]
7use dioxus::prelude::Store;
8use easer::functions::{Easing, Linear};
9pub use instant::Duration;
10
11/// Configuration for tween-based animations
12///
13/// # Examples
14/// ```rust
15/// use dioxus_motion::Duration;
16/// use dioxus_motion::prelude::Tween;
17/// use easer::functions::Easing;
18/// let tween = Tween::new(Duration::from_secs(1))
19///     .with_easing(easer::functions::Cubic::ease_in_out);
20/// ```
21#[cfg_attr(feature = "dioxus", derive(Store))]
22#[derive(Debug, Clone, Copy)]
23pub struct Tween {
24    /// Duration of the animation
25    pub duration: Duration,
26    /// Easing function for interpolation
27    pub easing: fn(f32, f32, f32, f32) -> f32,
28}
29
30impl PartialEq for Tween {
31    fn eq(&self, other: &Self) -> bool {
32        self.duration == other.duration && std::ptr::fn_addr_eq(self.easing, other.easing)
33    }
34}
35
36/// Default tween configuration with 300ms duration and linear easing
37impl Default for Tween {
38    fn default() -> Self {
39        Self {
40            duration: Duration::from_millis(300),
41            easing: Linear::ease_in_out,
42        }
43    }
44}
45
46impl Tween {
47    /// Creates a new tween with specified duration and linear easing
48    pub fn new(duration: Duration) -> Self {
49        Self {
50            duration,
51            easing: Linear::ease_in_out,
52        }
53    }
54
55    /// Sets the easing function for the animation
56    ///
57    /// # Arguments
58    /// * `easing` - Function that takes (t, b, c, d) and returns interpolated value
59    pub fn with_easing(mut self, easing: fn(f32, f32, f32, f32) -> f32) -> Self {
60        self.easing = easing;
61        self
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use easer::functions::{Cubic, Easing};
69
70    #[test]
71    fn test_tween_new() {
72        let tween = Tween {
73            duration: Duration::from_secs(1),
74            easing: Cubic::ease_in_out,
75        };
76
77        assert_eq!(tween.duration, Duration::from_secs(1));
78    }
79
80    #[test]
81    fn test_tween_interpolation() {
82        let tween = Tween {
83            duration: Duration::from_secs(1),
84            easing: Linear::ease_in_out,
85        };
86
87        // Test midpoint
88        let progress = 0.5;
89        let result = (tween.easing)(progress, 0.0, 1.0, 1.0);
90        assert!((result - 0.5).abs() < f32::EPSILON);
91
92        // Test start
93        let result = (tween.easing)(0.0, 0.0, 1.0, 1.0);
94        assert!((result - 0.0).abs() < f32::EPSILON);
95
96        // Test end
97        let result = (tween.easing)(1.0, 0.0, 1.0, 1.0);
98        assert!((result - 1.0).abs() < f32::EPSILON);
99    }
100
101    #[test]
102    fn test_tween_partial_eq_uses_function_identity() {
103        let base = Tween::new(Duration::from_secs(1));
104
105        assert_eq!(base, Tween::new(Duration::from_secs(1)));
106        assert_ne!(base, Tween::new(Duration::from_secs(2)));
107        assert_ne!(base, base.with_easing(Cubic::ease_in_out));
108    }
109}