| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- package animation
- import (
- "sync"
- "time"
- "fyne.io/fyne/v2"
- )
- // Runner is the main driver for animations package
- type Runner struct {
- animationMutex sync.RWMutex
- animations []*anim
- pendingAnimations []*anim
- runnerStarted bool
- }
- // Start will register the passed application and initiate its ticking.
- func (r *Runner) Start(a *fyne.Animation) {
- r.animationMutex.Lock()
- defer r.animationMutex.Unlock()
- if !r.runnerStarted {
- r.runnerStarted = true
- r.animations = append(r.animations, newAnim(a))
- r.runAnimations()
- } else {
- r.pendingAnimations = append(r.pendingAnimations, newAnim(a))
- }
- }
- // Stop causes an animation to stop ticking (if it was still running) and removes it from the runner.
- func (r *Runner) Stop(a *fyne.Animation) {
- r.animationMutex.Lock()
- defer r.animationMutex.Unlock()
- newList := make([]*anim, 0, len(r.animations))
- stopped := false
- for _, item := range r.animations {
- if item.a != a {
- newList = append(newList, item)
- } else {
- item.setStopped()
- stopped = true
- }
- }
- r.animations = newList
- if stopped {
- return
- }
- newList = make([]*anim, 0, len(r.pendingAnimations))
- for _, item := range r.pendingAnimations {
- if item.a != a {
- newList = append(newList, item)
- } else {
- item.setStopped()
- }
- }
- r.pendingAnimations = newList
- }
- func (r *Runner) runAnimations() {
- draw := time.NewTicker(time.Second / 60)
- go func() {
- for done := false; !done; {
- <-draw.C
- r.animationMutex.Lock()
- oldList := r.animations
- r.animationMutex.Unlock()
- newList := make([]*anim, 0, len(oldList))
- for _, a := range oldList {
- if !a.isStopped() && r.tickAnimation(a) {
- newList = append(newList, a)
- }
- }
- r.animationMutex.Lock()
- r.animations = append(newList, r.pendingAnimations...)
- r.pendingAnimations = nil
- done = len(r.animations) == 0
- r.animationMutex.Unlock()
- }
- r.animationMutex.Lock()
- r.runnerStarted = false
- r.animationMutex.Unlock()
- draw.Stop()
- }()
- }
- // tickAnimation will process a frame of animation and return true if this should continue animating
- func (r *Runner) tickAnimation(a *anim) bool {
- if time.Now().After(a.end) {
- if a.reverse {
- a.a.Tick(0.0)
- if a.repeatsLeft == 0 {
- return false
- }
- a.reverse = false
- } else {
- a.a.Tick(1.0)
- if a.a.AutoReverse {
- a.reverse = true
- }
- }
- if !a.reverse {
- if a.repeatsLeft == 0 {
- return false
- }
- if a.repeatsLeft > 0 {
- a.repeatsLeft--
- }
- }
- a.start = time.Now()
- a.end = a.start.Add(a.a.Duration)
- return true
- }
- delta := time.Since(a.start).Milliseconds()
- val := float32(delta) / float32(a.total)
- curve := a.a.Curve
- if curve == nil {
- curve = fyne.AnimationEaseInOut
- }
- if a.reverse {
- a.a.Tick(curve(1 - val))
- } else {
- a.a.Tick(curve(val))
- }
- return true
- }
|