@animini/core
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -5,7 +5,7 @@ 'use strict'; | ||
var spring = require('../../dist/spring-29172f7f.cjs.dev.js'); | ||
require('memoize-one'); | ||
var algorithms_dist_animiniCoreAlgorithms = require('../../dist/index-4e459fe7.cjs.dev.js'); | ||
exports.spring = spring.spring; | ||
exports.lerp = algorithms_dist_animiniCoreAlgorithms.lerp$1; | ||
exports.spring = algorithms_dist_animiniCoreAlgorithms.spring; |
@@ -5,7 +5,7 @@ 'use strict'; | ||
var spring = require('../../dist/spring-1813db30.cjs.prod.js'); | ||
require('memoize-one'); | ||
var algorithms_dist_animiniCoreAlgorithms = require('../../dist/index-4183db81.cjs.prod.js'); | ||
exports.spring = spring.spring; | ||
exports.lerp = algorithms_dist_animiniCoreAlgorithms.lerp$1; | ||
exports.spring = algorithms_dist_animiniCoreAlgorithms.spring; |
@@ -1,2 +0,1 @@ | ||
export { s as spring } from '../../dist/spring-49c90c8c.esm.js'; | ||
import 'memoize-one'; | ||
export { d as lerp, s as spring } from '../../dist/index-788165de.esm.js'; |
# @animini/core | ||
## 0.0.5 | ||
### Patch Changes | ||
- 098cac2: feat: one controller for all simultaneous values | ||
## 0.0.4 | ||
@@ -4,0 +10,0 @@ |
@@ -6,7 +6,55 @@ 'use strict'; | ||
var react = require('react'); | ||
var spring = require('./spring-29172f7f.cjs.dev.js'); | ||
require('memoize-one'); | ||
var algorithms_dist_animiniCoreAlgorithms = require('./index-4e459fe7.cjs.dev.js'); | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
if (enumerableOnly) symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(Object(source), true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function AnimatedValue(parent, index) { | ||
this.distance = this.velocity = 0; | ||
this.x0 = this.v0 = this.velocity = 0; | ||
this.idle = true; | ||
@@ -17,18 +65,6 @@ this.parent = parent; | ||
AnimatedValue.prototype = { | ||
get fn() { | ||
return this.parent.fn; | ||
get to() { | ||
return this.index !== -1 ? this.parent.to[this.index] : this.parent.to; | ||
}, | ||
get config() { | ||
return this.parent.config; | ||
}, | ||
get time() { | ||
return this.parent.time; | ||
}, | ||
get target() { | ||
return this.index !== -1 ? this.parent.target[this.index] : this.parent.target; | ||
}, | ||
get value() { | ||
@@ -45,19 +81,19 @@ return this.index !== -1 ? this.parent._value[this.index] : this.parent._value; | ||
AnimatedValue.prototype.start = function () { | ||
this.previousValue = this.value; | ||
this.idle = this.target === this.value; | ||
this.startVelocity = this.velocity; | ||
this.previousValue = this.from = this.value; | ||
this.idle = this.to === this.value; | ||
if (this.config.immediate) { | ||
this.value = this.target; | ||
} else if (!this.idle) { | ||
this.distance = this.target - this.value; | ||
this.precision = Math.min(1, Math.abs(this.distance) * 0.001); | ||
if (!this.idle) { | ||
this.v0 = this.velocity; | ||
this.x0 = this.to - this.from; | ||
this.precision = algorithms_dist_animiniCoreAlgorithms.clamp(Math.abs(this.x0) * 0.001, 0.001, 1); | ||
} | ||
}; | ||
AnimatedValue.prototype.update = function () { | ||
AnimatedValue.prototype.update = function (immediate, getProgress, dt) { | ||
if (this.idle) return; | ||
if (immediate) this.value = this.to; | ||
if (this.value === this.target) { | ||
if (this.value === this.to) { | ||
this.idle = true; | ||
this.velocity = 0; | ||
return; | ||
@@ -67,54 +103,81 @@ } | ||
this.previousValue = this.value; | ||
this.value = this.fn(); | ||
this.velocity = (this.value - this.previousValue) / this.time.delta; | ||
const progress = getProgress(this); | ||
this.value = algorithms_dist_animiniCoreAlgorithms.lerp(this.from, this.to, progress); | ||
this.velocity = (this.value - this.previousValue) / dt; | ||
const isMoving = Math.abs(this.velocity) > this.precision; | ||
const isTravelling = Math.abs(this.target - this.value) > this.precision; | ||
const isTravelling = Math.abs(this.to - this.value) > this.precision; | ||
this.idle = !isMoving && !isTravelling; | ||
if (this.idle) this.value = this.target; | ||
if (this.idle) { | ||
this.value = this.to; | ||
this.velocity = 0; | ||
} | ||
}; | ||
function lerp(v0, v1, t) { | ||
return v0 * (1 - t) + v1 * t; | ||
function MotionController(key, config, frameLoop) { | ||
var _this$_algorithm$setu; | ||
this.config = config; | ||
this.progress = 0; | ||
this._key = key; | ||
this._algorithm = algorithms_dist_animiniCoreAlgorithms.algorithms[config.motion]; | ||
(_this$_algorithm$setu = this._algorithm.setup) === null || _this$_algorithm$setu === void 0 ? void 0 : _this$_algorithm$setu.call(this); | ||
this._removed = false; | ||
this._internalTime = { | ||
elapsed: 0 | ||
}; | ||
this._createdAt = frameLoop.time.elapsed; | ||
this._frameLoop = frameLoop; | ||
} | ||
function equal(v0, v1) { | ||
if (Array.isArray(v0)) { | ||
return v0.every((val, index) => val === v1[index]); | ||
MotionController.prototype.update = function () { | ||
const loopTime = this._frameLoop.time; | ||
const firstFrame = loopTime.elapsed === this._createdAt; | ||
if (!this._removed && !firstFrame) { | ||
removeFromAvailableControllers(this); | ||
} | ||
return v0 === v1; | ||
if (this._internalTime.lastUpdate === loopTime.elapsed) return; | ||
this._internalTime.lastUpdate = loopTime.elapsed; | ||
this._internalTime.elapsed += loopTime.delta; | ||
this._internalTime.delta = loopTime.delta; | ||
const [progress, getProgress] = this._algorithm.solver.call(this); | ||
this.progress = progress; | ||
this.getProgress = getProgress; | ||
}; | ||
const AvailableControllers = new Map(); | ||
function removeFromAvailableControllers(ctrl) { | ||
AvailableControllers.get(ctrl._key).delete(ctrl._createdAt); | ||
ctrl._removed = true; | ||
} | ||
function each(array, iterator) { | ||
if (Array.isArray(array)) { | ||
for (let i = 0; i < array.length; i++) iterator(array[i], i); | ||
} else { | ||
iterator(array, -1); | ||
} | ||
} | ||
function map(obj, iterator) { | ||
if (typeof obj === 'object') { | ||
if (Array.isArray(obj)) { | ||
return obj.map(iterator); | ||
} | ||
return Object.entries(obj).map(([key, value]) => iterator(value, key)); | ||
function getAvailableController(config = { | ||
motion: 'lerp', | ||
factor: 0.05 | ||
}, frameLoop) { | ||
const configKey = JSON.stringify(config); | ||
const motionTimestamp = frameLoop.time.elapsed; | ||
if (!AvailableControllers.has(configKey)) AvailableControllers.set(configKey, new Map()); | ||
const motionForConfig = AvailableControllers.get(configKey); | ||
if (!motionForConfig.has(motionTimestamp)) { | ||
const controller = new MotionController(configKey, config, frameLoop); | ||
motionForConfig.set(motionTimestamp, controller); | ||
} | ||
return iterator(obj, -1); | ||
return motionForConfig.get(motionTimestamp); | ||
} | ||
function lerpFn() { | ||
return lerp(this.value, this.target, this.config.factor || 0.05); | ||
} | ||
function Animated(value, fn, adapter, loop) { | ||
this.config = {}; | ||
this.time = {}; | ||
this.loop = loop; | ||
this.adapter = adapter; | ||
function Animated(value, adapter, frameLoop) { | ||
this._adapter = adapter; | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this._children = algorithms_dist_animiniCoreAlgorithms.map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._movingChildren = 0; | ||
this.onUpdate = adapter === null || adapter === void 0 ? void 0 : adapter.onUpdate; | ||
this.parse = adapter === null || adapter === void 0 ? void 0 : adapter.parse; | ||
this._movingChildren = 0; | ||
this.setFn(fn); | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this.children = map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._frameLoop = frameLoop; | ||
} | ||
@@ -127,5 +190,5 @@ Animated.prototype = { | ||
get value() { | ||
var _this$adapter; | ||
var _this$_adapter; | ||
return (_this$adapter = this.adapter) !== null && _this$adapter !== void 0 && _this$adapter.format ? this.adapter.format(this._value) : this._value; | ||
return (_this$_adapter = this._adapter) !== null && _this$_adapter !== void 0 && _this$_adapter.format ? this._adapter.format(this._value) : this._value; | ||
} | ||
@@ -135,24 +198,10 @@ | ||
Animated.prototype.setFn = function (fn = lerpFn) { | ||
if (typeof fn === 'function') { | ||
this.fn = fn; | ||
this.onStart = undefined; | ||
} else { | ||
this.fn = fn.update; | ||
if (fn.onStart) this.onStart = fn.onStart; | ||
if (fn.memo) this.memo = fn.memo(); | ||
} | ||
}; | ||
Animated.prototype.start = function (to, config) { | ||
var _this$_adapter2; | ||
Animated.prototype.start = function (target, config = {}) { | ||
this.time.elapsed = 0; | ||
this.target = this.parse ? this.parse(target) : target; | ||
this.to = (_this$_adapter2 = this._adapter) !== null && _this$_adapter2 !== void 0 && _this$_adapter2.parse ? this._adapter.parse(to) : to; | ||
this.config = config; | ||
this._ctrl = undefined; | ||
this._movingChildren = 0; | ||
this.config = config; | ||
if (!this.config.immediate) { | ||
this.onStart && this.onStart(); | ||
} | ||
each(this.children, child => { | ||
algorithms_dist_animiniCoreAlgorithms.each(this._children, child => { | ||
child.start(); | ||
@@ -164,7 +213,18 @@ if (!child.idle) this._movingChildren++; | ||
Animated.prototype.update = function () { | ||
this.time.elapsed += this.loop.time.delta; | ||
this.time.delta = this.loop.time.delta; | ||
each(this.children, child => { | ||
if (this.idle) return; | ||
const immediate = this.config.immediate; | ||
if (!immediate) { | ||
if (!this._ctrl) { | ||
this._ctrl = getAvailableController(this.config, this._frameLoop); | ||
} | ||
this._ctrl.update(); | ||
} | ||
algorithms_dist_animiniCoreAlgorithms.each(this._children, child => { | ||
if (!child.idle) { | ||
child.update(); | ||
var _this$_ctrl; | ||
child.update(immediate, (_this$_ctrl = this._ctrl) === null || _this$_ctrl === void 0 ? void 0 : _this$_ctrl.getProgress, this._frameLoop.time.delta); | ||
if (child.idle) this._movingChildren--; | ||
@@ -183,6 +243,12 @@ } | ||
this.queue = new Set(); | ||
this.time = {}; | ||
this.time = { | ||
start: 0, | ||
elapsed: 0, | ||
delta: 0, | ||
_elapsed: 0 | ||
}; | ||
} | ||
FrameLoop.prototype.tick = function () { | ||
if (!this.running) return; | ||
this.update(); | ||
@@ -193,3 +259,2 @@ this.rafId = window.requestAnimationFrame(this.tick.bind(this)); | ||
FrameLoop.prototype.update = function () { | ||
if (!this.running) return; | ||
this.updateTime(); | ||
@@ -207,4 +272,4 @@ this.queue.forEach(cb => cb()); | ||
}; | ||
this.running = true; | ||
this.tick(); | ||
this.running = true; | ||
} | ||
@@ -241,11 +306,7 @@ }; | ||
function useAniminiCore(target, elementPayload, fn) { | ||
function useAniminiCore(motion = 'lerp', target, elementPayload) { | ||
const loop = target.loop || GlobalLoop; | ||
const rafId = react.useRef(); | ||
const el = react.useRef(null); | ||
const rawValues = react.useRef({}); | ||
const animations = react.useMemo(() => new Map(), []); | ||
react.useEffect(() => { | ||
animations.forEach(animated => animated.setFn(fn)); | ||
}, [fn, animations]); | ||
const update = react.useCallback(() => { | ||
@@ -267,3 +328,3 @@ var _target$setValues; | ||
}, [target, animations]); | ||
const start = react.useCallback((to, config) => { | ||
const start = react.useCallback((to, config = {}) => { | ||
let idle = true; | ||
@@ -275,3 +336,3 @@ | ||
const _animated = new Animated(value, fn, adapter, loop); | ||
const _animated = new Animated(value, adapter, loop); | ||
@@ -282,8 +343,13 @@ animations.set(key, _animated); | ||
const animated = animations.get(key); | ||
animated.start(to[key], typeof config === 'function' ? config(key) : config); | ||
const _config = typeof config === 'function' ? config(key) : _objectSpread2({}, config); | ||
if (!_config.motion) _config.motion = motion; | ||
animated.start(to[key], _config); | ||
idle &= animated.idle; | ||
} | ||
if (!idle) rafId.current = loop.start(update); | ||
}, [update, fn, animations]); | ||
loop.start(update); | ||
if (!idle) loop.start(update); | ||
}, [motion, update, animations]); | ||
react.useEffect(() => { | ||
@@ -299,9 +365,10 @@ return () => loop.stop(update); | ||
exports.spring = spring.spring; | ||
exports.clamp = algorithms_dist_animiniCoreAlgorithms.clamp; | ||
exports.each = algorithms_dist_animiniCoreAlgorithms.each; | ||
exports.equal = algorithms_dist_animiniCoreAlgorithms.equal; | ||
exports.lerp = algorithms_dist_animiniCoreAlgorithms.lerp; | ||
exports.map = algorithms_dist_animiniCoreAlgorithms.map; | ||
exports.spring = algorithms_dist_animiniCoreAlgorithms.spring; | ||
exports.FrameLoop = FrameLoop; | ||
exports.GlobalLoop = GlobalLoop; | ||
exports.each = each; | ||
exports.equal = equal; | ||
exports.lerp = lerp; | ||
exports.map = map; | ||
exports.useAniminiCore = useAniminiCore; |
@@ -6,7 +6,55 @@ 'use strict'; | ||
var react = require('react'); | ||
var spring = require('./spring-1813db30.cjs.prod.js'); | ||
require('memoize-one'); | ||
var algorithms_dist_animiniCoreAlgorithms = require('./index-4183db81.cjs.prod.js'); | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
if (enumerableOnly) symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(Object(source), true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function AnimatedValue(parent, index) { | ||
this.distance = this.velocity = 0; | ||
this.x0 = this.v0 = this.velocity = 0; | ||
this.idle = true; | ||
@@ -17,18 +65,6 @@ this.parent = parent; | ||
AnimatedValue.prototype = { | ||
get fn() { | ||
return this.parent.fn; | ||
get to() { | ||
return this.index !== -1 ? this.parent.to[this.index] : this.parent.to; | ||
}, | ||
get config() { | ||
return this.parent.config; | ||
}, | ||
get time() { | ||
return this.parent.time; | ||
}, | ||
get target() { | ||
return this.index !== -1 ? this.parent.target[this.index] : this.parent.target; | ||
}, | ||
get value() { | ||
@@ -45,19 +81,19 @@ return this.index !== -1 ? this.parent._value[this.index] : this.parent._value; | ||
AnimatedValue.prototype.start = function () { | ||
this.previousValue = this.value; | ||
this.idle = this.target === this.value; | ||
this.startVelocity = this.velocity; | ||
this.previousValue = this.from = this.value; | ||
this.idle = this.to === this.value; | ||
if (this.config.immediate) { | ||
this.value = this.target; | ||
} else if (!this.idle) { | ||
this.distance = this.target - this.value; | ||
this.precision = Math.min(1, Math.abs(this.distance) * 0.001); | ||
if (!this.idle) { | ||
this.v0 = this.velocity; | ||
this.x0 = this.to - this.from; | ||
this.precision = algorithms_dist_animiniCoreAlgorithms.clamp(Math.abs(this.x0) * 0.001, 0.001, 1); | ||
} | ||
}; | ||
AnimatedValue.prototype.update = function () { | ||
AnimatedValue.prototype.update = function (immediate, getProgress, dt) { | ||
if (this.idle) return; | ||
if (immediate) this.value = this.to; | ||
if (this.value === this.target) { | ||
if (this.value === this.to) { | ||
this.idle = true; | ||
this.velocity = 0; | ||
return; | ||
@@ -67,54 +103,81 @@ } | ||
this.previousValue = this.value; | ||
this.value = this.fn(); | ||
this.velocity = (this.value - this.previousValue) / this.time.delta; | ||
const progress = getProgress(this); | ||
this.value = algorithms_dist_animiniCoreAlgorithms.lerp(this.from, this.to, progress); | ||
this.velocity = (this.value - this.previousValue) / dt; | ||
const isMoving = Math.abs(this.velocity) > this.precision; | ||
const isTravelling = Math.abs(this.target - this.value) > this.precision; | ||
const isTravelling = Math.abs(this.to - this.value) > this.precision; | ||
this.idle = !isMoving && !isTravelling; | ||
if (this.idle) this.value = this.target; | ||
if (this.idle) { | ||
this.value = this.to; | ||
this.velocity = 0; | ||
} | ||
}; | ||
function lerp(v0, v1, t) { | ||
return v0 * (1 - t) + v1 * t; | ||
function MotionController(key, config, frameLoop) { | ||
var _this$_algorithm$setu; | ||
this.config = config; | ||
this.progress = 0; | ||
this._key = key; | ||
this._algorithm = algorithms_dist_animiniCoreAlgorithms.algorithms[config.motion]; | ||
(_this$_algorithm$setu = this._algorithm.setup) === null || _this$_algorithm$setu === void 0 ? void 0 : _this$_algorithm$setu.call(this); | ||
this._removed = false; | ||
this._internalTime = { | ||
elapsed: 0 | ||
}; | ||
this._createdAt = frameLoop.time.elapsed; | ||
this._frameLoop = frameLoop; | ||
} | ||
function equal(v0, v1) { | ||
if (Array.isArray(v0)) { | ||
return v0.every((val, index) => val === v1[index]); | ||
MotionController.prototype.update = function () { | ||
const loopTime = this._frameLoop.time; | ||
const firstFrame = loopTime.elapsed === this._createdAt; | ||
if (!this._removed && !firstFrame) { | ||
removeFromAvailableControllers(this); | ||
} | ||
return v0 === v1; | ||
if (this._internalTime.lastUpdate === loopTime.elapsed) return; | ||
this._internalTime.lastUpdate = loopTime.elapsed; | ||
this._internalTime.elapsed += loopTime.delta; | ||
this._internalTime.delta = loopTime.delta; | ||
const [progress, getProgress] = this._algorithm.solver.call(this); | ||
this.progress = progress; | ||
this.getProgress = getProgress; | ||
}; | ||
const AvailableControllers = new Map(); | ||
function removeFromAvailableControllers(ctrl) { | ||
AvailableControllers.get(ctrl._key).delete(ctrl._createdAt); | ||
ctrl._removed = true; | ||
} | ||
function each(array, iterator) { | ||
if (Array.isArray(array)) { | ||
for (let i = 0; i < array.length; i++) iterator(array[i], i); | ||
} else { | ||
iterator(array, -1); | ||
} | ||
} | ||
function map(obj, iterator) { | ||
if (typeof obj === 'object') { | ||
if (Array.isArray(obj)) { | ||
return obj.map(iterator); | ||
} | ||
return Object.entries(obj).map(([key, value]) => iterator(value, key)); | ||
function getAvailableController(config = { | ||
motion: 'lerp', | ||
factor: 0.05 | ||
}, frameLoop) { | ||
const configKey = JSON.stringify(config); | ||
const motionTimestamp = frameLoop.time.elapsed; | ||
if (!AvailableControllers.has(configKey)) AvailableControllers.set(configKey, new Map()); | ||
const motionForConfig = AvailableControllers.get(configKey); | ||
if (!motionForConfig.has(motionTimestamp)) { | ||
const controller = new MotionController(configKey, config, frameLoop); | ||
motionForConfig.set(motionTimestamp, controller); | ||
} | ||
return iterator(obj, -1); | ||
return motionForConfig.get(motionTimestamp); | ||
} | ||
function lerpFn() { | ||
return lerp(this.value, this.target, this.config.factor || 0.05); | ||
} | ||
function Animated(value, fn, adapter, loop) { | ||
this.config = {}; | ||
this.time = {}; | ||
this.loop = loop; | ||
this.adapter = adapter; | ||
function Animated(value, adapter, frameLoop) { | ||
this._adapter = adapter; | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this._children = algorithms_dist_animiniCoreAlgorithms.map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._movingChildren = 0; | ||
this.onUpdate = adapter === null || adapter === void 0 ? void 0 : adapter.onUpdate; | ||
this.parse = adapter === null || adapter === void 0 ? void 0 : adapter.parse; | ||
this._movingChildren = 0; | ||
this.setFn(fn); | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this.children = map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._frameLoop = frameLoop; | ||
} | ||
@@ -127,5 +190,5 @@ Animated.prototype = { | ||
get value() { | ||
var _this$adapter; | ||
var _this$_adapter; | ||
return (_this$adapter = this.adapter) !== null && _this$adapter !== void 0 && _this$adapter.format ? this.adapter.format(this._value) : this._value; | ||
return (_this$_adapter = this._adapter) !== null && _this$_adapter !== void 0 && _this$_adapter.format ? this._adapter.format(this._value) : this._value; | ||
} | ||
@@ -135,24 +198,10 @@ | ||
Animated.prototype.setFn = function (fn = lerpFn) { | ||
if (typeof fn === 'function') { | ||
this.fn = fn; | ||
this.onStart = undefined; | ||
} else { | ||
this.fn = fn.update; | ||
if (fn.onStart) this.onStart = fn.onStart; | ||
if (fn.memo) this.memo = fn.memo(); | ||
} | ||
}; | ||
Animated.prototype.start = function (to, config) { | ||
var _this$_adapter2; | ||
Animated.prototype.start = function (target, config = {}) { | ||
this.time.elapsed = 0; | ||
this.target = this.parse ? this.parse(target) : target; | ||
this.to = (_this$_adapter2 = this._adapter) !== null && _this$_adapter2 !== void 0 && _this$_adapter2.parse ? this._adapter.parse(to) : to; | ||
this.config = config; | ||
this._ctrl = undefined; | ||
this._movingChildren = 0; | ||
this.config = config; | ||
if (!this.config.immediate) { | ||
this.onStart && this.onStart(); | ||
} | ||
each(this.children, child => { | ||
algorithms_dist_animiniCoreAlgorithms.each(this._children, child => { | ||
child.start(); | ||
@@ -164,7 +213,18 @@ if (!child.idle) this._movingChildren++; | ||
Animated.prototype.update = function () { | ||
this.time.elapsed += this.loop.time.delta; | ||
this.time.delta = this.loop.time.delta; | ||
each(this.children, child => { | ||
if (this.idle) return; | ||
const immediate = this.config.immediate; | ||
if (!immediate) { | ||
if (!this._ctrl) { | ||
this._ctrl = getAvailableController(this.config, this._frameLoop); | ||
} | ||
this._ctrl.update(); | ||
} | ||
algorithms_dist_animiniCoreAlgorithms.each(this._children, child => { | ||
if (!child.idle) { | ||
child.update(); | ||
var _this$_ctrl; | ||
child.update(immediate, (_this$_ctrl = this._ctrl) === null || _this$_ctrl === void 0 ? void 0 : _this$_ctrl.getProgress, this._frameLoop.time.delta); | ||
if (child.idle) this._movingChildren--; | ||
@@ -183,6 +243,12 @@ } | ||
this.queue = new Set(); | ||
this.time = {}; | ||
this.time = { | ||
start: 0, | ||
elapsed: 0, | ||
delta: 0, | ||
_elapsed: 0 | ||
}; | ||
} | ||
FrameLoop.prototype.tick = function () { | ||
if (!this.running) return; | ||
this.update(); | ||
@@ -193,3 +259,2 @@ this.rafId = window.requestAnimationFrame(this.tick.bind(this)); | ||
FrameLoop.prototype.update = function () { | ||
if (!this.running) return; | ||
this.updateTime(); | ||
@@ -207,4 +272,4 @@ this.queue.forEach(cb => cb()); | ||
}; | ||
this.running = true; | ||
this.tick(); | ||
this.running = true; | ||
} | ||
@@ -241,11 +306,7 @@ }; | ||
function useAniminiCore(target, elementPayload, fn) { | ||
function useAniminiCore(motion = 'lerp', target, elementPayload) { | ||
const loop = target.loop || GlobalLoop; | ||
const rafId = react.useRef(); | ||
const el = react.useRef(null); | ||
const rawValues = react.useRef({}); | ||
const animations = react.useMemo(() => new Map(), []); | ||
react.useEffect(() => { | ||
animations.forEach(animated => animated.setFn(fn)); | ||
}, [fn, animations]); | ||
const update = react.useCallback(() => { | ||
@@ -267,3 +328,3 @@ var _target$setValues; | ||
}, [target, animations]); | ||
const start = react.useCallback((to, config) => { | ||
const start = react.useCallback((to, config = {}) => { | ||
let idle = true; | ||
@@ -275,3 +336,3 @@ | ||
const _animated = new Animated(value, fn, adapter, loop); | ||
const _animated = new Animated(value, adapter, loop); | ||
@@ -282,8 +343,13 @@ animations.set(key, _animated); | ||
const animated = animations.get(key); | ||
animated.start(to[key], typeof config === 'function' ? config(key) : config); | ||
const _config = typeof config === 'function' ? config(key) : _objectSpread2({}, config); | ||
if (!_config.motion) _config.motion = motion; | ||
animated.start(to[key], _config); | ||
idle &= animated.idle; | ||
} | ||
if (!idle) rafId.current = loop.start(update); | ||
}, [update, fn, animations]); | ||
loop.start(update); | ||
if (!idle) loop.start(update); | ||
}, [motion, update, animations]); | ||
react.useEffect(() => { | ||
@@ -299,9 +365,10 @@ return () => loop.stop(update); | ||
exports.spring = spring.spring; | ||
exports.clamp = algorithms_dist_animiniCoreAlgorithms.clamp; | ||
exports.each = algorithms_dist_animiniCoreAlgorithms.each; | ||
exports.equal = algorithms_dist_animiniCoreAlgorithms.equal; | ||
exports.lerp = algorithms_dist_animiniCoreAlgorithms.lerp; | ||
exports.map = algorithms_dist_animiniCoreAlgorithms.map; | ||
exports.spring = algorithms_dist_animiniCoreAlgorithms.spring; | ||
exports.FrameLoop = FrameLoop; | ||
exports.GlobalLoop = GlobalLoop; | ||
exports.each = each; | ||
exports.equal = equal; | ||
exports.lerp = lerp; | ||
exports.map = map; | ||
exports.useAniminiCore = useAniminiCore; |
@@ -1,7 +0,56 @@ | ||
import { useRef, useMemo, useEffect, useCallback } from 'react'; | ||
export { s as spring } from './spring-49c90c8c.esm.js'; | ||
import 'memoize-one'; | ||
import { useRef, useMemo, useCallback, useEffect } from 'react'; | ||
import { c as clamp, l as lerp, a as algorithms, m as map, e as each } from './index-788165de.esm.js'; | ||
export { c as clamp, e as each, b as equal, l as lerp, m as map, s as spring } from './index-788165de.esm.js'; | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
if (enumerableOnly) symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(Object(source), true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function AnimatedValue(parent, index) { | ||
this.distance = this.velocity = 0; | ||
this.x0 = this.v0 = this.velocity = 0; | ||
this.idle = true; | ||
@@ -12,18 +61,6 @@ this.parent = parent; | ||
AnimatedValue.prototype = { | ||
get fn() { | ||
return this.parent.fn; | ||
get to() { | ||
return this.index !== -1 ? this.parent.to[this.index] : this.parent.to; | ||
}, | ||
get config() { | ||
return this.parent.config; | ||
}, | ||
get time() { | ||
return this.parent.time; | ||
}, | ||
get target() { | ||
return this.index !== -1 ? this.parent.target[this.index] : this.parent.target; | ||
}, | ||
get value() { | ||
@@ -40,19 +77,19 @@ return this.index !== -1 ? this.parent._value[this.index] : this.parent._value; | ||
AnimatedValue.prototype.start = function () { | ||
this.previousValue = this.value; | ||
this.idle = this.target === this.value; | ||
this.startVelocity = this.velocity; | ||
this.previousValue = this.from = this.value; | ||
this.idle = this.to === this.value; | ||
if (this.config.immediate) { | ||
this.value = this.target; | ||
} else if (!this.idle) { | ||
this.distance = this.target - this.value; | ||
this.precision = Math.min(1, Math.abs(this.distance) * 0.001); | ||
if (!this.idle) { | ||
this.v0 = this.velocity; | ||
this.x0 = this.to - this.from; | ||
this.precision = clamp(Math.abs(this.x0) * 0.001, 0.001, 1); | ||
} | ||
}; | ||
AnimatedValue.prototype.update = function () { | ||
AnimatedValue.prototype.update = function (immediate, getProgress, dt) { | ||
if (this.idle) return; | ||
if (immediate) this.value = this.to; | ||
if (this.value === this.target) { | ||
if (this.value === this.to) { | ||
this.idle = true; | ||
this.velocity = 0; | ||
return; | ||
@@ -62,54 +99,81 @@ } | ||
this.previousValue = this.value; | ||
this.value = this.fn(); | ||
this.velocity = (this.value - this.previousValue) / this.time.delta; | ||
const progress = getProgress(this); | ||
this.value = lerp(this.from, this.to, progress); | ||
this.velocity = (this.value - this.previousValue) / dt; | ||
const isMoving = Math.abs(this.velocity) > this.precision; | ||
const isTravelling = Math.abs(this.target - this.value) > this.precision; | ||
const isTravelling = Math.abs(this.to - this.value) > this.precision; | ||
this.idle = !isMoving && !isTravelling; | ||
if (this.idle) this.value = this.target; | ||
if (this.idle) { | ||
this.value = this.to; | ||
this.velocity = 0; | ||
} | ||
}; | ||
function lerp(v0, v1, t) { | ||
return v0 * (1 - t) + v1 * t; | ||
function MotionController(key, config, frameLoop) { | ||
var _this$_algorithm$setu; | ||
this.config = config; | ||
this.progress = 0; | ||
this._key = key; | ||
this._algorithm = algorithms[config.motion]; | ||
(_this$_algorithm$setu = this._algorithm.setup) === null || _this$_algorithm$setu === void 0 ? void 0 : _this$_algorithm$setu.call(this); | ||
this._removed = false; | ||
this._internalTime = { | ||
elapsed: 0 | ||
}; | ||
this._createdAt = frameLoop.time.elapsed; | ||
this._frameLoop = frameLoop; | ||
} | ||
function equal(v0, v1) { | ||
if (Array.isArray(v0)) { | ||
return v0.every((val, index) => val === v1[index]); | ||
MotionController.prototype.update = function () { | ||
const loopTime = this._frameLoop.time; | ||
const firstFrame = loopTime.elapsed === this._createdAt; | ||
if (!this._removed && !firstFrame) { | ||
removeFromAvailableControllers(this); | ||
} | ||
return v0 === v1; | ||
if (this._internalTime.lastUpdate === loopTime.elapsed) return; | ||
this._internalTime.lastUpdate = loopTime.elapsed; | ||
this._internalTime.elapsed += loopTime.delta; | ||
this._internalTime.delta = loopTime.delta; | ||
const [progress, getProgress] = this._algorithm.solver.call(this); | ||
this.progress = progress; | ||
this.getProgress = getProgress; | ||
}; | ||
const AvailableControllers = new Map(); | ||
function removeFromAvailableControllers(ctrl) { | ||
AvailableControllers.get(ctrl._key).delete(ctrl._createdAt); | ||
ctrl._removed = true; | ||
} | ||
function each(array, iterator) { | ||
if (Array.isArray(array)) { | ||
for (let i = 0; i < array.length; i++) iterator(array[i], i); | ||
} else { | ||
iterator(array, -1); | ||
} | ||
} | ||
function map(obj, iterator) { | ||
if (typeof obj === 'object') { | ||
if (Array.isArray(obj)) { | ||
return obj.map(iterator); | ||
} | ||
return Object.entries(obj).map(([key, value]) => iterator(value, key)); | ||
function getAvailableController(config = { | ||
motion: 'lerp', | ||
factor: 0.05 | ||
}, frameLoop) { | ||
const configKey = JSON.stringify(config); | ||
const motionTimestamp = frameLoop.time.elapsed; | ||
if (!AvailableControllers.has(configKey)) AvailableControllers.set(configKey, new Map()); | ||
const motionForConfig = AvailableControllers.get(configKey); | ||
if (!motionForConfig.has(motionTimestamp)) { | ||
const controller = new MotionController(configKey, config, frameLoop); | ||
motionForConfig.set(motionTimestamp, controller); | ||
} | ||
return iterator(obj, -1); | ||
return motionForConfig.get(motionTimestamp); | ||
} | ||
function lerpFn() { | ||
return lerp(this.value, this.target, this.config.factor || 0.05); | ||
} | ||
function Animated(value, fn, adapter, loop) { | ||
this.config = {}; | ||
this.time = {}; | ||
this.loop = loop; | ||
this.adapter = adapter; | ||
function Animated(value, adapter, frameLoop) { | ||
this._adapter = adapter; | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this._children = map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._movingChildren = 0; | ||
this.onUpdate = adapter === null || adapter === void 0 ? void 0 : adapter.onUpdate; | ||
this.parse = adapter === null || adapter === void 0 ? void 0 : adapter.parse; | ||
this._movingChildren = 0; | ||
this.setFn(fn); | ||
this._value = adapter !== null && adapter !== void 0 && adapter.parseInitial ? adapter.parseInitial(value) : value; | ||
this.children = map(this._value, (_v, i) => new AnimatedValue(this, i)); | ||
this._frameLoop = frameLoop; | ||
} | ||
@@ -122,5 +186,5 @@ Animated.prototype = { | ||
get value() { | ||
var _this$adapter; | ||
var _this$_adapter; | ||
return (_this$adapter = this.adapter) !== null && _this$adapter !== void 0 && _this$adapter.format ? this.adapter.format(this._value) : this._value; | ||
return (_this$_adapter = this._adapter) !== null && _this$_adapter !== void 0 && _this$_adapter.format ? this._adapter.format(this._value) : this._value; | ||
} | ||
@@ -130,24 +194,10 @@ | ||
Animated.prototype.setFn = function (fn = lerpFn) { | ||
if (typeof fn === 'function') { | ||
this.fn = fn; | ||
this.onStart = undefined; | ||
} else { | ||
this.fn = fn.update; | ||
if (fn.onStart) this.onStart = fn.onStart; | ||
if (fn.memo) this.memo = fn.memo(); | ||
} | ||
}; | ||
Animated.prototype.start = function (to, config) { | ||
var _this$_adapter2; | ||
Animated.prototype.start = function (target, config = {}) { | ||
this.time.elapsed = 0; | ||
this.target = this.parse ? this.parse(target) : target; | ||
this.to = (_this$_adapter2 = this._adapter) !== null && _this$_adapter2 !== void 0 && _this$_adapter2.parse ? this._adapter.parse(to) : to; | ||
this.config = config; | ||
this._ctrl = undefined; | ||
this._movingChildren = 0; | ||
this.config = config; | ||
if (!this.config.immediate) { | ||
this.onStart && this.onStart(); | ||
} | ||
each(this.children, child => { | ||
each(this._children, child => { | ||
child.start(); | ||
@@ -159,7 +209,18 @@ if (!child.idle) this._movingChildren++; | ||
Animated.prototype.update = function () { | ||
this.time.elapsed += this.loop.time.delta; | ||
this.time.delta = this.loop.time.delta; | ||
each(this.children, child => { | ||
if (this.idle) return; | ||
const immediate = this.config.immediate; | ||
if (!immediate) { | ||
if (!this._ctrl) { | ||
this._ctrl = getAvailableController(this.config, this._frameLoop); | ||
} | ||
this._ctrl.update(); | ||
} | ||
each(this._children, child => { | ||
if (!child.idle) { | ||
child.update(); | ||
var _this$_ctrl; | ||
child.update(immediate, (_this$_ctrl = this._ctrl) === null || _this$_ctrl === void 0 ? void 0 : _this$_ctrl.getProgress, this._frameLoop.time.delta); | ||
if (child.idle) this._movingChildren--; | ||
@@ -178,6 +239,12 @@ } | ||
this.queue = new Set(); | ||
this.time = {}; | ||
this.time = { | ||
start: 0, | ||
elapsed: 0, | ||
delta: 0, | ||
_elapsed: 0 | ||
}; | ||
} | ||
FrameLoop.prototype.tick = function () { | ||
if (!this.running) return; | ||
this.update(); | ||
@@ -188,3 +255,2 @@ this.rafId = window.requestAnimationFrame(this.tick.bind(this)); | ||
FrameLoop.prototype.update = function () { | ||
if (!this.running) return; | ||
this.updateTime(); | ||
@@ -202,4 +268,4 @@ this.queue.forEach(cb => cb()); | ||
}; | ||
this.running = true; | ||
this.tick(); | ||
this.running = true; | ||
} | ||
@@ -236,11 +302,7 @@ }; | ||
function useAniminiCore(target, elementPayload, fn) { | ||
function useAniminiCore(motion = 'lerp', target, elementPayload) { | ||
const loop = target.loop || GlobalLoop; | ||
const rafId = useRef(); | ||
const el = useRef(null); | ||
const rawValues = useRef({}); | ||
const animations = useMemo(() => new Map(), []); | ||
useEffect(() => { | ||
animations.forEach(animated => animated.setFn(fn)); | ||
}, [fn, animations]); | ||
const update = useCallback(() => { | ||
@@ -262,3 +324,3 @@ var _target$setValues; | ||
}, [target, animations]); | ||
const start = useCallback((to, config) => { | ||
const start = useCallback((to, config = {}) => { | ||
let idle = true; | ||
@@ -270,3 +332,3 @@ | ||
const _animated = new Animated(value, fn, adapter, loop); | ||
const _animated = new Animated(value, adapter, loop); | ||
@@ -277,8 +339,13 @@ animations.set(key, _animated); | ||
const animated = animations.get(key); | ||
animated.start(to[key], typeof config === 'function' ? config(key) : config); | ||
const _config = typeof config === 'function' ? config(key) : _objectSpread2({}, config); | ||
if (!_config.motion) _config.motion = motion; | ||
animated.start(to[key], _config); | ||
idle &= animated.idle; | ||
} | ||
if (!idle) rafId.current = loop.start(update); | ||
}, [update, fn, animations]); | ||
loop.start(update); | ||
if (!idle) loop.start(update); | ||
}, [motion, update, animations]); | ||
useEffect(() => { | ||
@@ -294,2 +361,2 @@ return () => loop.stop(update); | ||
export { FrameLoop, GlobalLoop, each, equal, lerp, map, useAniminiCore }; | ||
export { FrameLoop, GlobalLoop, useAniminiCore }; |
{ | ||
"name": "@animini/core", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "small animation lib", | ||
@@ -5,0 +5,0 @@ "keywords": [], |
export { spring } from './spring' | ||
export { lerp } from './lerp' |
@@ -1,3 +0,1 @@ | ||
import memoizeOne from 'memoize-one' | ||
function getSpringConfig(k, c, m, v0) { | ||
@@ -11,27 +9,27 @@ const zeta = c / (2 * Math.sqrt(k * m)) | ||
export const spring = { | ||
memo() { | ||
return memoizeOne(getSpringConfig) | ||
}, | ||
onStart() { | ||
defaultConfig: { tension: 170, friction: 26, mass: 1 }, | ||
setup() { | ||
const { tension = 170, friction = 26, mass = 1, velocity } = this.config | ||
this._config = this.memo(tension, friction, mass, velocity) | ||
this._config = getSpringConfig(tension, friction, mass, velocity) | ||
}, | ||
solver() { | ||
const t = this._internalTime.elapsed | ||
const { zeta, w1, w0 } = this._config | ||
update() { | ||
const t = this.time.elapsed | ||
const { zeta, w1, w0, v0 = this.startVelocity ?? 0 } = this.parent._config | ||
const { target: to, distance: x0 } = this | ||
let value, fn | ||
let value | ||
if (zeta < 1) { | ||
// value = to - envelope * (((-v0 + zeta * w0 * x0) / w1) * Math.sin(w1 * t) + x0 * Math.cos(w1 * t)) | ||
const envelope = Math.exp(-zeta * w0 * t) | ||
value = to - envelope * (((-v0 + zeta * w0 * x0) / w1) * Math.sin(w1 * t) + x0 * Math.cos(w1 * t)) | ||
value = 1 - envelope * (((zeta * w0) / w1) * Math.sin(w1 * t) + Math.cos(w1 * t)) | ||
fn = (v) => v * (envelope / w1) * Math.sin(w1 * t) | ||
} else { | ||
// value = to - envelope * (x0 + (-v0 + w0 * x0) * t) | ||
const envelope = Math.exp(-w0 * t) | ||
value = to - envelope * (x0 + (-v0 + w0 * x0) * t) | ||
value = 1 - envelope * (1 + w0 * t) | ||
fn = (v) => v * envelope * t | ||
} | ||
return value | ||
return [value, (animatedValue) => value + fn(animatedValue.v0 / animatedValue.x0)] | ||
}, | ||
} |
import { AnimatedValue } from './AnimatedValue' | ||
import { each, map, lerp } from '../utils' | ||
import { getAvailableController } from './MotionController' | ||
import { each, map } from '../utils' | ||
function lerpFn() { | ||
return lerp(this.value, this.target, this.config.factor || 0.05) | ||
} | ||
export function Animated(value, adapter, frameLoop) { | ||
this._adapter = adapter | ||
this._value = adapter?.parseInitial ? adapter.parseInitial(value) : value | ||
this._children = map(this._value, (_v, i) => new AnimatedValue(this, i)) | ||
this._movingChildren = 0 | ||
export function Animated(value, fn, adapter, loop) { | ||
this.config = {} | ||
this.time = {} | ||
this.loop = loop | ||
this.adapter = adapter | ||
this.onUpdate = adapter?.onUpdate | ||
this.parse = adapter?.parse | ||
this._movingChildren = 0 | ||
this.setFn(fn) | ||
this._value = adapter?.parseInitial ? adapter.parseInitial(value) : value | ||
this.children = map(this._value, (_v, i) => new AnimatedValue(this, i)) | ||
this._frameLoop = frameLoop | ||
} | ||
@@ -29,27 +20,13 @@ | ||
get value() { | ||
return this.adapter?.format ? this.adapter.format(this._value) : this._value | ||
return this._adapter?.format ? this._adapter.format(this._value) : this._value | ||
}, | ||
} | ||
Animated.prototype.setFn = function (fn = lerpFn) { | ||
if (typeof fn === 'function') { | ||
this.fn = fn | ||
this.onStart = undefined | ||
} else { | ||
this.fn = fn.update | ||
if (fn.onStart) this.onStart = fn.onStart | ||
if (fn.memo) this.memo = fn.memo() | ||
} | ||
} | ||
Animated.prototype.start = function (to, config) { | ||
this.to = this._adapter?.parse ? this._adapter.parse(to) : to | ||
this.config = config | ||
this._ctrl = undefined | ||
Animated.prototype.start = function (target, config = {}) { | ||
this.time.elapsed = 0 | ||
this.target = this.parse ? this.parse(target) : target | ||
this._movingChildren = 0 | ||
this.config = config | ||
if (!this.config.immediate) { | ||
this.onStart && this.onStart() | ||
} | ||
each(this.children, (child) => { | ||
each(this._children, (child) => { | ||
child.start() | ||
@@ -61,8 +38,15 @@ if (!child.idle) this._movingChildren++ | ||
Animated.prototype.update = function () { | ||
this.time.elapsed += this.loop.time.delta | ||
this.time.delta = this.loop.time.delta | ||
if (this.idle) return | ||
each(this.children, (child) => { | ||
const immediate = this.config.immediate | ||
if (!immediate) { | ||
if (!this._ctrl) { | ||
this._ctrl = getAvailableController(this.config, this._frameLoop) | ||
} | ||
this._ctrl.update() | ||
} | ||
each(this._children, (child) => { | ||
if (!child.idle) { | ||
child.update() | ||
child.update(immediate, this._ctrl?.getProgress, this._frameLoop.time.delta) | ||
if (child.idle) this._movingChildren-- | ||
@@ -69,0 +53,0 @@ } |
@@ -0,3 +1,5 @@ | ||
import { lerp, clamp } from '../utils' | ||
export function AnimatedValue(parent, index) { | ||
this.distance = this.velocity = 0 | ||
this.x0 = this.v0 = this.velocity = 0 | ||
this.idle = true | ||
@@ -9,14 +11,5 @@ this.parent = parent | ||
AnimatedValue.prototype = { | ||
get fn() { | ||
return this.parent.fn | ||
get to() { | ||
return this.index !== -1 ? this.parent.to[this.index] : this.parent.to | ||
}, | ||
get config() { | ||
return this.parent.config | ||
}, | ||
get time() { | ||
return this.parent.time | ||
}, | ||
get target() { | ||
return this.index !== -1 ? this.parent.target[this.index] : this.parent.target | ||
}, | ||
get value() { | ||
@@ -31,18 +24,19 @@ return this.index !== -1 ? this.parent._value[this.index] : this.parent._value | ||
AnimatedValue.prototype.start = function () { | ||
this.previousValue = this.value | ||
this.idle = this.target === this.value | ||
this.startVelocity = this.velocity | ||
this.previousValue = this.from = this.value | ||
this.idle = this.to === this.value | ||
if (this.config.immediate) { | ||
this.value = this.target | ||
} else if (!this.idle) { | ||
this.distance = this.target - this.value | ||
this.precision = Math.min(1, Math.abs(this.distance) * 0.001) | ||
if (!this.idle) { | ||
this.v0 = this.velocity | ||
this.x0 = this.to - this.from | ||
this.precision = clamp(Math.abs(this.x0) * 0.001, 0.001, 1) | ||
} | ||
} | ||
AnimatedValue.prototype.update = function () { | ||
AnimatedValue.prototype.update = function (immediate, getProgress, dt) { | ||
if (this.idle) return | ||
if (this.value === this.target) { | ||
if (immediate) this.value = this.to | ||
if (this.value === this.to) { | ||
this.idle = true | ||
this.velocity = 0 | ||
return | ||
@@ -52,12 +46,16 @@ } | ||
this.previousValue = this.value | ||
this.value = this.fn() | ||
const progress = getProgress(this) | ||
this.velocity = (this.value - this.previousValue) / this.time.delta | ||
this.value = lerp(this.from, this.to, progress) | ||
this.velocity = (this.value - this.previousValue) / dt | ||
const isMoving = Math.abs(this.velocity) > this.precision | ||
const isTravelling = Math.abs(this.target - this.value) > this.precision | ||
const isTravelling = Math.abs(this.to - this.value) > this.precision | ||
this.idle = !isMoving && !isTravelling | ||
if (this.idle) this.value = this.target | ||
if (this.idle) { | ||
this.value = this.to | ||
this.velocity = 0 | ||
} | ||
} |
@@ -9,6 +9,7 @@ function now() { | ||
this.queue = new Set() | ||
this.time = {} | ||
this.time = { start: 0, elapsed: 0, delta: 0, _elapsed: 0 } | ||
} | ||
FrameLoop.prototype.tick = function () { | ||
if (!this.running) return | ||
this.update() | ||
@@ -19,3 +20,2 @@ this.rafId = window.requestAnimationFrame(this.tick.bind(this)) | ||
FrameLoop.prototype.update = function () { | ||
if (!this.running) return | ||
this.updateTime() | ||
@@ -28,4 +28,4 @@ this.queue.forEach((cb) => cb()) | ||
this.time = { start: now(), elapsed: 0, delta: 0, _elapsed: 0 } | ||
this.running = true | ||
this.tick() | ||
this.running = true | ||
} | ||
@@ -32,0 +32,0 @@ } |
@@ -5,5 +5,4 @@ import { useRef, useCallback, useEffect, useMemo } from 'react' | ||
export function useAniminiCore(target, elementPayload, fn) { | ||
export function useAniminiCore(motion = 'lerp', target, elementPayload) { | ||
const loop = target.loop || GlobalLoop | ||
const rafId = useRef() | ||
@@ -14,6 +13,2 @@ const el = useRef(null) | ||
useEffect(() => { | ||
animations.forEach((animated) => animated.setFn(fn)) | ||
}, [fn, animations]) | ||
const update = useCallback(() => { | ||
@@ -29,2 +24,3 @@ if (!el.current) return | ||
}) | ||
target.setValues?.(rawValues.current, el.current, elementPayload) | ||
@@ -36,3 +32,3 @@ if (idle) loop.stop(update) | ||
const start = useCallback( | ||
(to, config) => { | ||
(to, config = {}) => { | ||
let idle = true | ||
@@ -42,13 +38,17 @@ for (let key in to) { | ||
const [value, adapter] = target.getInitialValueAndAdapter(el.current, key, elementPayload) | ||
const animated = new Animated(value, fn, adapter, loop) | ||
const animated = new Animated(value, adapter, loop) | ||
animations.set(key, animated) | ||
} | ||
const animated = animations.get(key) | ||
animated.start(to[key], typeof config === 'function' ? config(key) : config) | ||
const _config = typeof config === 'function' ? config(key) : { ...config } | ||
if (!_config.motion) _config.motion = motion | ||
animated.start(to[key], _config) | ||
idle &= animated.idle | ||
} | ||
if (!idle) rafId.current = loop.start(update) | ||
loop.start(update) | ||
if (!idle) loop.start(update) | ||
}, | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[update, fn, animations] | ||
[motion, update, animations] | ||
) | ||
@@ -55,0 +55,0 @@ |
@@ -7,2 +7,6 @@ // https://github.com/mattdesl/lerp | ||
export function clamp(value, min, max) { | ||
return Math.max(min, Math.min(max, value)) | ||
} | ||
export function equal(v0, v1) { | ||
@@ -9,0 +13,0 @@ if (Array.isArray(v0)) { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
49753
24
1490
1