aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/component/widget/Animate.scala
blob: 0e848aa949927678ea1c35aac37eb3284668f4cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package reading.component.widget

import scala.collection.mutable.Map

import org.scalajs.dom.{ window, document }
import org.scalajs.dom.raw.HTMLElement

object Animate {
  val animationFrames: Map[String, Int] = Map.empty

  def apply(
    id: String,
    duration: Double,
    transition: (Double, Double) => Double,
    animate: (Double, HTMLElement) => Unit,
    onEnd: => Unit = ()
  ): Unit = {
    animationFrames.get(id) match {
      case Some(animationFrame) => window.cancelAnimationFrame(animationFrame)
      case None => ()
    }
    val animationFrame = window.requestAnimationFrame(ts =>
      frame(id, ts, duration, transition, animate, onEnd)(ts))
    animationFrames.put(id, animationFrame)
    ()
  }

  private def frame(
    id: String,
    start: Double,
    duration: Double,
    transition: (Double, Double) => Double,
    animate: (Double, HTMLElement) => Unit,
    onEnd: => Unit
  )(
    timestamp: Double
  ): Unit = {
    document.getElementById(id).asInstanceOf[HTMLElement] match {
      case element: HTMLElement =>
        val elapsed = timestamp - start
        if (elapsed < duration) {
          animate(Transition.easeOut(elapsed, duration), element)
          val animationFrame = window.requestAnimationFrame(frame(id, start, duration, transition, animate, onEnd))
          animationFrames.put(id, animationFrame)
        } else {
          animate(1, element)
          onEnd
        }
      case _ =>
        val animationFrame = window.requestAnimationFrame(ts => frame(id, ts, duration, transition, animate, onEnd)(ts))
        animationFrames.put(id, animationFrame)
    }
    ()
  }
}