package zntg import "time" // Animation is a struct that keeps track of time for animation. type Animation struct { // The interval of the animation Interval time.Duration active bool start time.Time lastUpdate time.Duration } // NewAnimation creates an Animation given the specified interval. The animation is immediately started. func NewAnimation(interval time.Duration) Animation { return Animation{ Interval: interval, active: true, start: time.Now(), } } // NewAnimationPtr creates an Animation given the specified interval and returns a pointer to it. The animation is immediately started. func NewAnimationPtr(interval time.Duration) *Animation { ani := NewAnimation(interval) return &ani } // Animate checks if enough time as elapsed to animate a single interval and advances the single interval. func (a *Animation) Animate() bool { since := time.Since(a.start) if !a.active || since < a.lastUpdate+a.Interval { return false } a.lastUpdate += a.Interval return true } // AnimateDelta checks how many natural intervals have elapsed and advances that many intervals. Returns the total of time that has been advanced and the number of intervals. func (a *Animation) AnimateDelta() (time.Duration, int) { if !a.active { return 0, 0 } since := time.Since(a.start) n := (since - a.lastUpdate) / a.Interval delta := n * a.Interval a.lastUpdate += delta return delta, int(n) } // AnimateFn calls fn for every interval and advances that interval for every interval that has elapsed until it caught up again. func (a *Animation) AnimateFn(fn func()) { if !a.active { return } since := time.Since(a.start) for a.active && since > a.lastUpdate+a.Interval { fn() a.lastUpdate += a.Interval } } // Pause pauses the animation causing the Animate{,Delta,Fn} methods to do nothing. func (a *Animation) Pause() { a.active = false } // IsActive returns true when the animation is started (and false when it either was never started or paused) func (a *Animation) IsActive() bool { return a.active } // Start starts the animation (when paused or not started yet). func (a *Animation) Start() { if a.active { return } a.active = true a.start = time.Now() a.lastUpdate = 0 }