summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/utils
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app/utils')
-rw-r--r--animism-align/frontend/app/utils/index.js2
-rw-r--r--animism-align/frontend/app/utils/oktween.js163
2 files changed, 165 insertions, 0 deletions
diff --git a/animism-align/frontend/app/utils/index.js b/animism-align/frontend/app/utils/index.js
index 0f5a1dd..855fcaf 100644
--- a/animism-align/frontend/app/utils/index.js
+++ b/animism-align/frontend/app/utils/index.js
@@ -8,6 +8,7 @@ export const formatDateTime = dateStr => format(new Date(dateStr), 'd MMM yyyy H
export const formatDate = dateStr => format(new Date(dateStr), 'd MMM yyyy')
export const formatTime = dateStr => format(new Date(dateStr), 'H:mm')
export const formatAge = dateStr => formatDistance(new Date(), new Date(dateStr)) + ' ago.'
+export const toArray = a => Array.from(a)
/* Mobile check */
@@ -93,6 +94,7 @@ export const clamp = (n, a=0, b=1) => n < a ? a : n < b ? n : b
export const dist = (x1, y1, x2, y2) => Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
export const mod = (n, m) => n - (m * Math.floor(n / m))
export const angle = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1)
+export const lerp = (n,a,b) => (b-a)*n+a
export const floatLT = (a,b) => ((a*10|0) < (b*10|0))
export const floatLTE = (a,b) => ((a*10|0) === (b*10|0) || floatLT(a,b))
export const floatGT = (a,b) => ((a*10|0) > (b*10|0))
diff --git a/animism-align/frontend/app/utils/oktween.js b/animism-align/frontend/app/utils/oktween.js
new file mode 100644
index 0000000..4388ad4
--- /dev/null
+++ b/animism-align/frontend/app/utils/oktween.js
@@ -0,0 +1,163 @@
+/*
+ oktween.add({
+ obj: el.style,
+ units: "px",
+ from: { left: 0 },
+ to: { left: 100 },
+ duration: 1000,
+ easing: oktween.easing.circ_out,
+ update: function(obj){
+ console.log(obj.left)
+ }
+ finished: function(){
+ console.log("done")
+ }
+ })
+*/
+
+import { lerp } from 'app/utils'
+
+const oktween = {}
+let tweens = []
+
+let last_t = 0
+let id = 0
+
+oktween.speed = 1
+oktween.add = (tween) => {
+ tween.id = id++
+ tween.obj = tween.obj || {}
+ if (tween.easing) {
+ if (typeof tween.easing === "string") {
+ tween.easing = oktween.easing[tween.easing]
+ }
+ } else {
+ tween.easing = oktween.easing.linear
+ }
+ if (!('from' in tween) && !('to' in tween)) {
+ tween.keys = []
+ } else if (!('from' in tween)) {
+ tween.from = {}
+ tween.keys = Object.keys(tween.to)
+ tween.keys.forEach(function(prop) {
+ tween.from[prop] = parseFloat(tween.obj[prop])
+ })
+ } else {
+ tween.keys = Object.keys(tween.from)
+ }
+ tween.delay = tween.delay || 0
+ tween.start = last_t + tween.delay
+ tween.done = false
+ tween.after = tween.after || []
+ tween.then = (fn) => { tween.after.push(fn); return tween }
+ tween.tick = 0
+ tween.skip = tween.skip || 1
+ tween.dt = 0
+ tweens.push(tween)
+ return tween
+}
+oktween.update = (t) => {
+ let done = false
+ requestAnimationFrame(oktween.update)
+ last_t = t * oktween.speed
+ if (tweens.length === 0) return
+ tweens.forEach((tween, i) => {
+ const dt = Math.min(1.0, (t - tween.start) / tween.duration)
+ tween.tick++
+ if (dt < 0 || (dt < 1 && (tween.tick % tween.skip != 0))) return
+ const ddt = tween.easing(dt)
+ tween.dt = ddt
+ tween.keys.forEach((prop) => {
+ let val = lerp(ddt, tween.from[prop], tween.to[prop])
+ if (tween.round) val = Math.round(val)
+ if (tween.units) val = (Math.round(val)) + tween.units
+ tween.obj[prop] = val
+ })
+ if (tween.update) {
+ tween.update(tween.obj, dt)
+ }
+ if (dt === 1) {
+ if (tween.finished) {
+ tween.finished(tween)
+ }
+ if (tween.after.length) {
+ const twn = tween.after.shift()
+ twn.obj = twn.obj || tween.obj
+ twn.after = tween.after
+ oktween.add(twn)
+ }
+ if (tween.loop) {
+ tween.start = t + tween.delay
+ }
+ else {
+ done = true
+ tween.done = true
+ }
+ }
+ })
+ if (done) {
+ tweens = tweens.filter(tween => !tween.done)
+ }
+}
+
+requestAnimationFrame(oktween.update)
+
+oktween.easing = {
+ linear: (t) => {
+ return t
+ },
+ circ_out: (t) => {
+ return Math.sqrt(1 - (t = t - 1) * t)
+ },
+ circ_in: (t) => {
+ return -(Math.sqrt(1 - (t * t)) - 1)
+ },
+ circ_in_out: (t) => {
+ return ((t*=2) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1)
+ },
+ quad_in: (n) => {
+ return Math.pow(n, 2)
+ },
+ quad_out: (n) => {
+ return n * (n - 2) * -1
+ },
+ quad_in_out: (n) => {
+ n = n * 2
+ if (n < 1) { return Math.pow(n, 2) / 2 }
+ return -1 * ((--n) * (n - 2) - 1) / 2
+ },
+ cubic_bezier: (mX1, mY1, mX2, mY2) => {
+ function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1 }
+ function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1 }
+ function C(aA1) { return 3.0 * aA1 }
+
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
+ function CalcBezier(aT, aA1, aA2) {
+ return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT
+ }
+
+ // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+ function GetSlope(aT, aA1, aA2) {
+ return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1)
+ }
+
+ function GetTForX(aX) {
+ // Newton raphson iteration
+ let aGuessT = aX
+ for (let i = 0; i < 10; ++i) {
+ const currentSlope = GetSlope(aGuessT, mX1, mX2)
+ if (currentSlope == 0.0) return aGuessT
+ const currentX = CalcBezier(aGuessT, mX1, mX2) - aX
+ aGuessT -= currentX / currentSlope
+ }
+ return aGuessT
+ }
+
+ return function (aX) {
+ if (mX1 == mY1 && mX2 == mY2) return aX // linear
+ return CalcBezier(aX, mY1, mY2)
+ }
+ }
+}
+
+export default oktween