diff options
Diffstat (limited to 'src/main/scala/reading/component/widget/Animate.scala')
-rw-r--r-- | src/main/scala/reading/component/widget/Animate.scala | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/main/scala/reading/component/widget/Animate.scala b/src/main/scala/reading/component/widget/Animate.scala new file mode 100644 index 0000000..0e848aa --- /dev/null +++ b/src/main/scala/reading/component/widget/Animate.scala @@ -0,0 +1,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) + } + () + } +} |