package utils import ( "math" "time" "gioui.org/layout" "gioui.org/op" ) type Animation struct { start float32 end float32 current float32 startTime time.Time duration time.Duration active bool Easing Easing } type Easing int const ( None Easing = iota EasingIn EasingOut EasingOutSine EasingInOutSine ) func (a *Animation) Current() float32 { return a.current } func applyEasing(easing Easing, t float32) float32 { switch easing { case EasingIn: return t * t case EasingOut: return t * (2 - t) case EasingOutSine: return float32(math.Sin(float64(t) * math.Pi / 2)) case EasingInOutSine: return float32(-0.5 * (math.Cos(math.Pi*float64(t)) - 1)) default: return t } } func (a *Animation) Start(start, end float32, duration time.Duration, easing Easing) { a.start = start a.end = end a.current = start a.startTime = time.Now() a.duration = duration a.Easing = easing a.active = true } func (a *Animation) Update(gtx layout.Context) float32 { if !a.active { return a.current } elapsed := time.Since(a.startTime) if elapsed >= a.duration { a.current = a.end a.active = false } else { progress := float32(elapsed) / float32(a.duration) eased := applyEasing(a.Easing, progress) a.current = a.start + (a.end-a.start)*eased } gtx.Execute(&op.InvalidateCmd{}) return a.current }