379 lines
8.4 KiB
JavaScript
379 lines
8.4 KiB
JavaScript
|
// Copyright (c) 2017 Adobe Systems Incorporated. All rights reserved.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
import eve from './eve.js'
|
||
|
import { Snap } from './svg.js'
|
||
|
|
||
|
var animations = {},
|
||
|
requestAnimFrame =
|
||
|
window.requestAnimationFrame ||
|
||
|
window.webkitRequestAnimationFrame ||
|
||
|
window.mozRequestAnimationFrame ||
|
||
|
window.oRequestAnimationFrame ||
|
||
|
window.msRequestAnimationFrame ||
|
||
|
function (callback) {
|
||
|
setTimeout(callback, 16, new Date().getTime())
|
||
|
return true
|
||
|
},
|
||
|
requestID,
|
||
|
isArray =
|
||
|
Array.isArray ||
|
||
|
function (a) {
|
||
|
return (
|
||
|
a instanceof Array ||
|
||
|
Object.prototype.toString.call(a) == '[object Array]'
|
||
|
)
|
||
|
},
|
||
|
idgen = 0,
|
||
|
idprefix = 'M' + (+new Date()).toString(36),
|
||
|
ID = function () {
|
||
|
return idprefix + (idgen++).toString(36)
|
||
|
},
|
||
|
diff = function (a, b, A, B) {
|
||
|
if (isArray(a)) {
|
||
|
res = []
|
||
|
for (var i = 0, ii = a.length; i < ii; i++) {
|
||
|
res[i] = diff(a[i], b, A[i], B)
|
||
|
}
|
||
|
return res
|
||
|
}
|
||
|
var dif = (A - a) / (B - b)
|
||
|
return function (bb) {
|
||
|
return a + dif * (bb - b)
|
||
|
}
|
||
|
},
|
||
|
timer =
|
||
|
Date.now ||
|
||
|
function () {
|
||
|
return +new Date()
|
||
|
},
|
||
|
sta = function (val) {
|
||
|
var a = this
|
||
|
if (val == null) {
|
||
|
return a.s
|
||
|
}
|
||
|
var ds = a.s - val
|
||
|
a.b += a.dur * ds
|
||
|
a.B += a.dur * ds
|
||
|
a.s = val
|
||
|
},
|
||
|
speed = function (val) {
|
||
|
var a = this
|
||
|
if (val == null) {
|
||
|
return a.spd
|
||
|
}
|
||
|
a.spd = val
|
||
|
},
|
||
|
duration = function (val) {
|
||
|
var a = this
|
||
|
if (val == null) {
|
||
|
return a.dur
|
||
|
}
|
||
|
a.s = (a.s * val) / a.dur
|
||
|
a.dur = val
|
||
|
},
|
||
|
stopit = function () {
|
||
|
var a = this
|
||
|
delete animations[a.id]
|
||
|
a.update()
|
||
|
eve('mina.stop.' + a.id, a)
|
||
|
},
|
||
|
pause = function () {
|
||
|
var a = this
|
||
|
if (a.pdif) {
|
||
|
return
|
||
|
}
|
||
|
delete animations[a.id]
|
||
|
a.update()
|
||
|
a.pdif = a.get() - a.b
|
||
|
},
|
||
|
resume = function () {
|
||
|
var a = this
|
||
|
if (!a.pdif) {
|
||
|
return
|
||
|
}
|
||
|
a.b = a.get() - a.pdif
|
||
|
delete a.pdif
|
||
|
animations[a.id] = a
|
||
|
frame()
|
||
|
},
|
||
|
update = function () {
|
||
|
var a = this,
|
||
|
res
|
||
|
if (isArray(a.start)) {
|
||
|
res = []
|
||
|
for (var j = 0, jj = a.start.length; j < jj; j++) {
|
||
|
res[j] = +a.start[j] + (a.end[j] - a.start[j]) * a.easing(a.s)
|
||
|
}
|
||
|
} else {
|
||
|
res = +a.start + (a.end - a.start) * a.easing(a.s)
|
||
|
}
|
||
|
a.set(res)
|
||
|
},
|
||
|
frame = function (timeStamp) {
|
||
|
// Manual invokation?
|
||
|
if (!timeStamp) {
|
||
|
// Frame loop stopped?
|
||
|
if (!requestID) {
|
||
|
// Start frame loop...
|
||
|
requestID = requestAnimFrame(frame)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
var len = 0
|
||
|
for (var i in animations)
|
||
|
if (animations.hasOwnProperty(i)) {
|
||
|
var a = animations[i],
|
||
|
b = a.get(),
|
||
|
res
|
||
|
len++
|
||
|
a.s = (b - a.b) / (a.dur / a.spd)
|
||
|
if (a.s >= 1) {
|
||
|
delete animations[i]
|
||
|
a.s = 1
|
||
|
len--
|
||
|
;(function (a) {
|
||
|
setTimeout(function () {
|
||
|
eve('mina.finish.' + a.id, a)
|
||
|
})
|
||
|
})(a)
|
||
|
}
|
||
|
a.update()
|
||
|
}
|
||
|
requestID = len ? requestAnimFrame(frame) : false
|
||
|
},
|
||
|
/*\
|
||
|
* mina
|
||
|
[ method ]
|
||
|
**
|
||
|
* Generic animation of numbers
|
||
|
**
|
||
|
- a (number) start _slave_ number
|
||
|
- A (number) end _slave_ number
|
||
|
- b (number) start _master_ number (start time in general case)
|
||
|
- B (number) end _master_ number (end time in general case)
|
||
|
- get (function) getter of _master_ number (see @mina.time)
|
||
|
- set (function) setter of _slave_ number
|
||
|
- easing (function) #optional easing function, default is @mina.linear
|
||
|
= (object) animation descriptor
|
||
|
o {
|
||
|
o id (string) animation id,
|
||
|
o start (number) start _slave_ number,
|
||
|
o end (number) end _slave_ number,
|
||
|
o b (number) start _master_ number,
|
||
|
o s (number) animation status (0..1),
|
||
|
o dur (number) animation duration,
|
||
|
o spd (number) animation speed,
|
||
|
o get (function) getter of _master_ number (see @mina.time),
|
||
|
o set (function) setter of _slave_ number,
|
||
|
o easing (function) easing function, default is @mina.linear,
|
||
|
o status (function) status getter/setter,
|
||
|
o speed (function) speed getter/setter,
|
||
|
o duration (function) duration getter/setter,
|
||
|
o stop (function) animation stopper
|
||
|
o pause (function) pauses the animation
|
||
|
o resume (function) resumes the animation
|
||
|
o update (function) calles setter with the right value of the animation
|
||
|
o }
|
||
|
\*/
|
||
|
mina = function (a, A, b, B, get, set, easing) {
|
||
|
var anim = {
|
||
|
id: ID(),
|
||
|
start: a,
|
||
|
end: A,
|
||
|
b: b,
|
||
|
s: 0,
|
||
|
dur: B - b,
|
||
|
spd: 1,
|
||
|
get: get,
|
||
|
set: set,
|
||
|
easing: easing || mina.linear,
|
||
|
status: sta,
|
||
|
speed: speed,
|
||
|
duration: duration,
|
||
|
stop: stopit,
|
||
|
pause: pause,
|
||
|
resume: resume,
|
||
|
update: update
|
||
|
}
|
||
|
animations[anim.id] = anim
|
||
|
var len = 0,
|
||
|
i
|
||
|
for (i in animations)
|
||
|
if (animations.hasOwnProperty(i)) {
|
||
|
len++
|
||
|
if (len == 2) {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
len == 1 && frame()
|
||
|
return anim
|
||
|
}
|
||
|
/*\
|
||
|
* mina.time
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns the current time. Equivalent to:
|
||
|
| function () {
|
||
|
| return (new Date).getTime();
|
||
|
| }
|
||
|
\*/
|
||
|
mina.time = timer
|
||
|
/*\
|
||
|
* mina.getById
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an animation by its id
|
||
|
- id (string) animation's id
|
||
|
= (object) See @mina
|
||
|
\*/
|
||
|
mina.getById = function (id) {
|
||
|
return animations[id] || null
|
||
|
}
|
||
|
|
||
|
/*\
|
||
|
* mina.linear
|
||
|
[ method ]
|
||
|
**
|
||
|
* Default linear easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.linear = function (n) {
|
||
|
return n
|
||
|
}
|
||
|
/*\
|
||
|
* mina.easeout
|
||
|
[ method ]
|
||
|
**
|
||
|
* Easeout easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.easeout = function (n) {
|
||
|
return Math.pow(n, 1.7)
|
||
|
}
|
||
|
/*\
|
||
|
* mina.easein
|
||
|
[ method ]
|
||
|
**
|
||
|
* Easein easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.easein = function (n) {
|
||
|
return Math.pow(n, 0.48)
|
||
|
}
|
||
|
/*\
|
||
|
* mina.easeinout
|
||
|
[ method ]
|
||
|
**
|
||
|
* Easeinout easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.easeinout = function (n) {
|
||
|
if (n == 1) {
|
||
|
return 1
|
||
|
}
|
||
|
if (n == 0) {
|
||
|
return 0
|
||
|
}
|
||
|
var q = 0.48 - n / 1.04,
|
||
|
Q = Math.sqrt(0.1734 + q * q),
|
||
|
x = Q - q,
|
||
|
X = Math.pow(Math.abs(x), 1 / 3) * (x < 0 ? -1 : 1),
|
||
|
y = -Q - q,
|
||
|
Y = Math.pow(Math.abs(y), 1 / 3) * (y < 0 ? -1 : 1),
|
||
|
t = X + Y + 0.5
|
||
|
return (1 - t) * 3 * t * t + t * t * t
|
||
|
}
|
||
|
/*\
|
||
|
* mina.backin
|
||
|
[ method ]
|
||
|
**
|
||
|
* Backin easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.backin = function (n) {
|
||
|
if (n == 1) {
|
||
|
return 1
|
||
|
}
|
||
|
var s = 1.70158
|
||
|
return n * n * ((s + 1) * n - s)
|
||
|
}
|
||
|
/*\
|
||
|
* mina.backout
|
||
|
[ method ]
|
||
|
**
|
||
|
* Backout easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.backout = function (n) {
|
||
|
if (n == 0) {
|
||
|
return 0
|
||
|
}
|
||
|
n = n - 1
|
||
|
var s = 1.70158
|
||
|
return n * n * ((s + 1) * n + s) + 1
|
||
|
}
|
||
|
/*\
|
||
|
* mina.elastic
|
||
|
[ method ]
|
||
|
**
|
||
|
* Elastic easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.elastic = function (n) {
|
||
|
if (n == !!n) {
|
||
|
return n
|
||
|
}
|
||
|
return (
|
||
|
Math.pow(2, -10 * n) * Math.sin(((n - 0.075) * (2 * Math.PI)) / 0.3) + 1
|
||
|
)
|
||
|
}
|
||
|
/*\
|
||
|
* mina.bounce
|
||
|
[ method ]
|
||
|
**
|
||
|
* Bounce easing
|
||
|
- n (number) input 0..1
|
||
|
= (number) output 0..1
|
||
|
\*/
|
||
|
mina.bounce = function (n) {
|
||
|
var s = 7.5625,
|
||
|
p = 2.75,
|
||
|
l
|
||
|
if (n < 1 / p) {
|
||
|
l = s * n * n
|
||
|
} else {
|
||
|
if (n < 2 / p) {
|
||
|
n -= 1.5 / p
|
||
|
l = s * n * n + 0.75
|
||
|
} else {
|
||
|
if (n < 2.5 / p) {
|
||
|
n -= 2.25 / p
|
||
|
l = s * n * n + 0.9375
|
||
|
} else {
|
||
|
n -= 2.625 / p
|
||
|
l = s * n * n + 0.984375
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
export default mina
|