fix(progress_bar): sync determinate animation clock on target change
This prevents the time delta from becoming very large when the widget hasn't animated for a bit, leading to snapping instead of a smooth animation. Also prevents animating on widget creation, since it doesn't feel good in `cosmic-osd`.
This commit is contained in:
parent
8b4c8adec8
commit
dad5f1e273
1 changed files with 25 additions and 16 deletions
|
|
@ -4,29 +4,38 @@ use std::time::Duration;
|
||||||
|
|
||||||
const LAG: f32 = 0.1;
|
const LAG: f32 = 0.1;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Progress {
|
pub struct Progress {
|
||||||
pub current: f32,
|
pub current: f32,
|
||||||
last: Instant,
|
target: Option<f32>,
|
||||||
}
|
last: Option<Instant>,
|
||||||
|
|
||||||
impl Default for Progress {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
current: 0.0,
|
|
||||||
last: Instant::now(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Progress {
|
impl Progress {
|
||||||
/// Smoothly chases `target` using exponential decay.
|
/// Smoothly chases `target` using exponential decay.
|
||||||
/// Returns `true` if still animating and a redraw should be requested.
|
/// Returns `true` if a redraw should be requested.
|
||||||
pub fn update(&mut self, target: f32, now: Instant) -> bool {
|
pub fn update(&mut self, target: f32, now: Instant) -> bool {
|
||||||
let dt = (now - self.last).as_secs_f32();
|
// Don't animate on start
|
||||||
self.last = now;
|
let Some(last) = self.last else {
|
||||||
let next = self.current + (target - self.current) * (1.0 - (-dt / LAG).exp());
|
self.current = target;
|
||||||
if (next - target).abs() > 0.001 {
|
self.target = Some(target);
|
||||||
self.current = next;
|
self.last = Some(now);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sync animation clock when target changes
|
||||||
|
if self.target != Some(target) {
|
||||||
|
self.target = Some(target);
|
||||||
|
self.last = Some(now);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dt = (now - last).as_secs_f32();
|
||||||
|
self.last = Some(now);
|
||||||
|
let diff = target - self.current;
|
||||||
|
|
||||||
|
if diff.abs() > 0.001 {
|
||||||
|
self.current += diff * (1.0 - (-dt / LAG).exp());
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
self.current = target;
|
self.current = target;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue