aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/component/widget/Animate.scala
blob: 632817720efb062931ef64fded109d5c6c840509 (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
56
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) =>
        ()
      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)
          animationFrames.remove(id)
          onEnd
        }
      case _ =>
        val animationFrame = window.requestAnimationFrame(ts => frame(id, ts, duration, transition, animate, onEnd)(ts))
        animationFrames.put(id, animationFrame)
    }
    ()
  }
}