mirror of
https://github.com/zhigang1992/react-native-reanimated.git
synced 2026-01-12 22:50:47 +08:00
Remove dependencies' cycles (#187)
The main problems were with setValue and interpolate so I made them not available internally and exposed it with addition class. In internal operation InternalAnimatedValue is used and it's not causing dependencies' cycles. Changed logic of exposing nodes. Now there's no need to import whole base.js for wrapped nodes.
This commit is contained in:
@@ -3,7 +3,7 @@ import Animation from './Animation';
|
||||
import decay from './decay';
|
||||
import { block, clockRunning, startClock, stopClock, cond } from '../base';
|
||||
import Clock from '../core/AnimatedClock';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
|
||||
class DecayAnimation extends Animation {
|
||||
constructor(config) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
import Animation from './Animation';
|
||||
import SpringConfig from '../SpringConfig';
|
||||
import spring from './spring';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
import timing from './timing';
|
||||
import { block, clockRunning, startClock, stopClock, cond } from '../base';
|
||||
import Clock from '../core/AnimatedClock';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
greaterThan,
|
||||
} from '../base';
|
||||
import { min, abs } from '../derived';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
|
||||
const MAX_STEPS_MS = 64;
|
||||
|
||||
|
||||
127
src/base.js
127
src/base.js
@@ -1,111 +1,16 @@
|
||||
import AnimatedCond from './core/AnimatedCond';
|
||||
import AnimatedSet from './core/AnimatedSet';
|
||||
import AnimatedOperator from './core/AnimatedOperator';
|
||||
import AnimatedStartClock from './core/AnimatedStartClock';
|
||||
import AnimatedStopClock from './core/AnimatedStopClock';
|
||||
import AnimatedClockTest from './core/AnimatedClockTest';
|
||||
import AnimatedDebug from './core/AnimatedDebug';
|
||||
import AnimatedCall from './core/AnimatedCall';
|
||||
import AnimatedEvent from './core/AnimatedEvent';
|
||||
import AnimatedAlways from './core/AnimatedAlways';
|
||||
import AnimatedConcat from './core/AnimatedConcat';
|
||||
|
||||
import { adapt } from './utils';
|
||||
|
||||
function operator(name) {
|
||||
return (...args) => new AnimatedOperator(name, args.map(adapt));
|
||||
}
|
||||
|
||||
export const add = operator('add');
|
||||
export const sub = operator('sub');
|
||||
export const multiply = operator('multiply');
|
||||
export const divide = operator('divide');
|
||||
export const pow = operator('pow');
|
||||
export const modulo = operator('modulo');
|
||||
export const sqrt = operator('sqrt');
|
||||
export const sin = operator('sin');
|
||||
export const cos = operator('cos');
|
||||
export const tan = operator('tan');
|
||||
export const acos = operator('acos');
|
||||
export const asin = operator('asin');
|
||||
export const atan = operator('atan');
|
||||
export const exp = operator('exp');
|
||||
export const round = operator('round');
|
||||
export const lessThan = operator('lessThan');
|
||||
export const eq = operator('eq');
|
||||
export const greaterThan = operator('greaterThan');
|
||||
export const lessOrEq = operator('lessOrEq');
|
||||
export const greaterOrEq = operator('greaterOrEq');
|
||||
export const neq = operator('neq');
|
||||
export const and = operator('and');
|
||||
export const or = operator('or');
|
||||
export const defined = operator('defined');
|
||||
export const not = operator('not');
|
||||
|
||||
export const set = function(what, value) {
|
||||
return new AnimatedSet(what, adapt(value));
|
||||
};
|
||||
|
||||
export const cond = function(cond, ifBlock, elseBlock) {
|
||||
return new AnimatedCond(
|
||||
adapt(cond),
|
||||
adapt(ifBlock),
|
||||
elseBlock === undefined ? undefined : adapt(elseBlock)
|
||||
);
|
||||
};
|
||||
|
||||
export const block = function(items) {
|
||||
return adapt(items);
|
||||
};
|
||||
|
||||
export const call = function(args, func) {
|
||||
return new AnimatedCall(args, func);
|
||||
};
|
||||
|
||||
export const debug = function(message, value) {
|
||||
if (__DEV__) {
|
||||
const runningInRemoteDebugger = typeof atob !== 'undefined';
|
||||
// hack to detect if app is running in remote debugger
|
||||
// https://stackoverflow.com/questions/39022216
|
||||
|
||||
const runningInExpoShell =
|
||||
global.Expo && global.Expo.Constants.appOwnership !== 'standalone';
|
||||
|
||||
if (runningInRemoteDebugger || runningInExpoShell) {
|
||||
// When running in expo or remote debugger we use JS console.log to output variables
|
||||
// otherwise we output to the native console using native debug node
|
||||
return block([
|
||||
call([value], ([a]) => console.log(`${message} ${a}`)),
|
||||
value,
|
||||
]);
|
||||
} else {
|
||||
return new AnimatedDebug(message, adapt(value));
|
||||
}
|
||||
}
|
||||
// Debugging is disabled in PROD
|
||||
return value;
|
||||
};
|
||||
|
||||
export const startClock = function(clock) {
|
||||
return new AnimatedStartClock(clock);
|
||||
};
|
||||
|
||||
export const always = function(item) {
|
||||
return new AnimatedAlways(item);
|
||||
};
|
||||
|
||||
export const concat = function(...args) {
|
||||
return new AnimatedConcat(args.map(adapt));
|
||||
};
|
||||
|
||||
export const stopClock = function(clock) {
|
||||
return new AnimatedStopClock(clock);
|
||||
};
|
||||
|
||||
export const clockRunning = function(clock) {
|
||||
return new AnimatedClockTest(clock);
|
||||
};
|
||||
|
||||
export const event = function(argMapping, config) {
|
||||
return new AnimatedEvent(argMapping, config);
|
||||
};
|
||||
export { createAnimatedCond as cond } from './core/AnimatedCond';
|
||||
export { createAnimatedSet as set } from './core/AnimatedSet';
|
||||
export {
|
||||
createAnimatedStartClock as startClock,
|
||||
} from './core/AnimatedStartClock';
|
||||
export { createAnimatedStopClock as stopClock } from './core/AnimatedStopClock';
|
||||
export {
|
||||
createAnimatedClockTest as clockRunning,
|
||||
} from './core/AnimatedClockTest';
|
||||
export { createAnimatedDebug as debug } from './core/AnimatedDebug';
|
||||
export { createAnimatedCall as call } from './core/AnimatedCall';
|
||||
export { createAnimatedEvent as event } from './core/AnimatedEvent';
|
||||
export { createAnimatedAlways as always } from './core/AnimatedAlways';
|
||||
export { createAnimatedConcat as concat } from './core/AnimatedConcat';
|
||||
export { createAnimatedBlock as block, adapt } from './core/AnimatedBlock';
|
||||
export * from './operators';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
|
||||
export default class AnimatedAlways extends AnimatedNode {
|
||||
class AnimatedAlways extends AnimatedNode {
|
||||
_what;
|
||||
|
||||
constructor(what) {
|
||||
@@ -12,3 +12,7 @@ export default class AnimatedAlways extends AnimatedNode {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedAlways(item) {
|
||||
return new AnimatedAlways(item);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
|
||||
// These values are established by empiricism with tests (tradeoff: performance VS precision)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import InternalAnimatedValue from './InternalAnimatedValue';
|
||||
|
||||
export default class AnimatedBlock extends AnimatedNode {
|
||||
class AnimatedBlock extends AnimatedNode {
|
||||
_array;
|
||||
|
||||
constructor(array) {
|
||||
@@ -17,3 +18,24 @@ export default class AnimatedBlock extends AnimatedNode {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedBlock(items) {
|
||||
return adapt(items);
|
||||
}
|
||||
|
||||
function nodify(v) {
|
||||
if (typeof v === 'object' && v.__isProxy) {
|
||||
if (!v.__val) {
|
||||
v.__val = new InternalAnimatedValue(0);
|
||||
}
|
||||
return v.__val;
|
||||
}
|
||||
// TODO: cache some typical static values (e.g. 0, 1, -1)
|
||||
return v instanceof AnimatedNode ? v : new InternalAnimatedValue(v);
|
||||
}
|
||||
|
||||
export function adapt(v) {
|
||||
return Array.isArray(v)
|
||||
? new AnimatedBlock(v.map(node => adapt(node)))
|
||||
: nodify(v);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ReanimatedEventEmitter from '../ReanimatedEventEmitter';
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
|
||||
const NODE_MAPPING = new Map();
|
||||
@@ -9,7 +9,7 @@ function listener(data) {
|
||||
node && node._callback(data.args);
|
||||
}
|
||||
|
||||
export default class AnimatedCall extends AnimatedNode {
|
||||
class AnimatedCall extends AnimatedNode {
|
||||
_callback;
|
||||
_args;
|
||||
|
||||
@@ -40,3 +40,7 @@ export default class AnimatedCall extends AnimatedNode {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedCall(args, func) {
|
||||
return new AnimatedCall(args, func);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import AnimatedValue from './AnimatedValue';
|
||||
import InternalAnimatedValue from './AnimatedValue';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
|
||||
class AnimatedMainClock extends AnimatedValue {
|
||||
class AnimatedMainClock extends InternalAnimatedValue {
|
||||
_frameCallback;
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -2,7 +2,7 @@ import AnimatedNode from './AnimatedNode';
|
||||
import AnimatedClock from './AnimatedClock';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
|
||||
export default class AnimatedClockTest extends AnimatedNode {
|
||||
class AnimatedClockTest extends AnimatedNode {
|
||||
_clockNode;
|
||||
|
||||
constructor(clockNode) {
|
||||
@@ -18,3 +18,7 @@ export default class AnimatedClockTest extends AnimatedNode {
|
||||
return this._clockNode.isStarted() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedClockTest(clock) {
|
||||
return new AnimatedClockTest(clock);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import AnimatedAlways from './AnimatedAlways';
|
||||
import { createAnimatedAlways } from './AnimatedAlways';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
|
||||
class Code extends React.Component {
|
||||
@@ -33,7 +33,7 @@ class Code extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
this.always = new AnimatedAlways(nodeExec || nodeChildren);
|
||||
this.always = createAnimatedAlways(nodeExec || nodeChildren);
|
||||
this.always.__attach();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
export default class AnimatedConcat extends AnimatedNode {
|
||||
class AnimatedConcat extends AnimatedNode {
|
||||
constructor(input) {
|
||||
super({ type: 'concat', input: input.map(n => n.__nodeID) }, input);
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedConcat(...args) {
|
||||
return new AnimatedConcat(args.map(adapt));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
export default class AnimatedCond extends AnimatedNode {
|
||||
class AnimatedCond extends AnimatedNode {
|
||||
_condition;
|
||||
_ifBlock;
|
||||
_elseBlock;
|
||||
@@ -29,3 +30,11 @@ export default class AnimatedCond extends AnimatedNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedCond(cond, ifBlock, elseBlock) {
|
||||
return new AnimatedCond(
|
||||
adapt(cond),
|
||||
adapt(ifBlock),
|
||||
elseBlock === undefined ? undefined : adapt(elseBlock)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { createAnimatedBlock as block, adapt } from './AnimatedBlock';
|
||||
import { createAnimatedCall as call } from './AnimatedCall';
|
||||
|
||||
export default class AnimatedDebug extends AnimatedNode {
|
||||
class AnimatedDebug extends AnimatedNode {
|
||||
_message;
|
||||
_value;
|
||||
|
||||
@@ -17,3 +19,27 @@ export default class AnimatedDebug extends AnimatedNode {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedDebug(message, value) {
|
||||
if (__DEV__) {
|
||||
const runningInRemoteDebugger = typeof atob !== 'undefined';
|
||||
// hack to detect if app is running in remote debugger
|
||||
// https://stackoverflow.com/questions/39022216
|
||||
|
||||
const runningInExpoShell =
|
||||
global.Expo && global.Expo.Constants.appOwnership !== 'standalone';
|
||||
|
||||
if (runningInRemoteDebugger || runningInExpoShell) {
|
||||
// When running in expo or remote debugger we use JS console.log to output variables
|
||||
// otherwise we output to the native console using native debug node
|
||||
return block([
|
||||
call([value], ([a]) => console.log(`${message} ${a}`)),
|
||||
value,
|
||||
]);
|
||||
} else {
|
||||
return new AnimatedDebug(message, adapt(value));
|
||||
}
|
||||
}
|
||||
// Debugging is disabled in PROD
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import { findNodeHandle } from 'react-native';
|
||||
import ReanimatedModule from '../ReanimatedModule';
|
||||
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import AnimatedValue from './AnimatedValue';
|
||||
import AnimatedAlways from './AnimatedAlways';
|
||||
import InternalAnimatedValue from './AnimatedValue';
|
||||
import { createAnimatedAlways } from './AnimatedAlways';
|
||||
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import createEventObjectProxyPolyfill from './createEventObjectProxyPolyfill';
|
||||
@@ -15,13 +15,13 @@ function sanitizeArgMapping(argMapping) {
|
||||
const alwaysNodes = [];
|
||||
|
||||
const traverse = (value, path) => {
|
||||
if (value instanceof AnimatedValue) {
|
||||
if (value instanceof InternalAnimatedValue) {
|
||||
eventMappings.push(path.concat(value.__nodeID));
|
||||
} else if (typeof value === 'object' && value.__val) {
|
||||
eventMappings.push(path.concat(value.__val.__nodeID));
|
||||
} else if (typeof value === 'function') {
|
||||
const node = new AnimatedValue(0);
|
||||
alwaysNodes.push(new AnimatedAlways(value(node)));
|
||||
const node = new InternalAnimatedValue(0);
|
||||
alwaysNodes.push(createAnimatedAlways(value(node)));
|
||||
eventMappings.push(path.concat(node.__nodeID));
|
||||
} else if (typeof value === 'object') {
|
||||
for (const key in value) {
|
||||
@@ -61,7 +61,7 @@ function sanitizeArgMapping(argMapping) {
|
||||
typeof Proxy === 'function'
|
||||
? new Proxy({}, proxyHandler)
|
||||
: createEventObjectProxyPolyfill();
|
||||
alwaysNodes.push(new AnimatedAlways(ev(proxy)));
|
||||
alwaysNodes.push(createAnimatedAlways(ev(proxy)));
|
||||
traverse(proxy, []);
|
||||
}
|
||||
|
||||
@@ -99,3 +99,7 @@ export default class AnimatedEvent extends AnimatedNode {
|
||||
this.__detach();
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedEvent(argMapping, config) {
|
||||
return new AnimatedEvent(argMapping, config);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
function reduce(fn) {
|
||||
return input => input.reduce((a, b) => fn(val(a), val(b)));
|
||||
@@ -53,7 +54,7 @@ const OPERATIONS = {
|
||||
neq: infix((a, b) => a != b),
|
||||
};
|
||||
|
||||
export default class AnimatedOperator extends AnimatedNode {
|
||||
class AnimatedOperator extends AnimatedNode {
|
||||
_input;
|
||||
_op;
|
||||
_operation;
|
||||
@@ -75,3 +76,7 @@ export default class AnimatedOperator extends AnimatedNode {
|
||||
return this._operation(this._input);
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedOperator(name) {
|
||||
return (...args) => new AnimatedOperator(name, args.map(adapt));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { val } from '../utils';
|
||||
import { val } from '../val';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
export default class AnimatedSet extends AnimatedNode {
|
||||
class AnimatedSet extends AnimatedNode {
|
||||
_what;
|
||||
_value;
|
||||
|
||||
@@ -17,3 +18,7 @@ export default class AnimatedSet extends AnimatedNode {
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedSet(what, value) {
|
||||
return new AnimatedSet(what, adapt(value));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import AnimatedNode from './AnimatedNode';
|
||||
import AnimatedClock from './AnimatedClock';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
|
||||
export default class AnimatedStartClock extends AnimatedNode {
|
||||
class AnimatedStartClock extends AnimatedNode {
|
||||
_clockNode;
|
||||
|
||||
constructor(clockNode) {
|
||||
@@ -19,3 +19,7 @@ export default class AnimatedStartClock extends AnimatedNode {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedStartClock(clock) {
|
||||
return new AnimatedStartClock(clock);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import AnimatedNode from './AnimatedNode';
|
||||
import AnimatedClock from './AnimatedClock';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
|
||||
export default class AnimatedStopClock extends AnimatedNode {
|
||||
class AnimatedStopClock extends AnimatedNode {
|
||||
_clockNode;
|
||||
|
||||
constructor(clockNode) {
|
||||
@@ -19,3 +19,7 @@ export default class AnimatedStopClock extends AnimatedNode {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function createAnimatedStopClock(clock) {
|
||||
return new AnimatedStopClock(clock);
|
||||
}
|
||||
|
||||
@@ -1,56 +1,10 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { set } from '../base';
|
||||
import { val } from '../utils';
|
||||
import { evaluateOnce } from '../derived/evaluateOnce';
|
||||
import { createAnimatedSet as set } from '../core/AnimatedSet';
|
||||
import interpolate from '../derived/interpolate';
|
||||
import ReanimatedModule from '../ReanimatedModule';
|
||||
|
||||
function sanitizeValue(value) {
|
||||
return value === null || value === undefined || typeof value === 'string'
|
||||
? value
|
||||
: Number(value);
|
||||
}
|
||||
|
||||
export default class AnimatedValue extends AnimatedNode {
|
||||
constructor(value) {
|
||||
super({ type: 'value', value: sanitizeValue(value) });
|
||||
this._startingValue = this._value = value;
|
||||
this._animation = null;
|
||||
}
|
||||
|
||||
__detach() {
|
||||
ReanimatedModule.getValue(
|
||||
this.__nodeID,
|
||||
val => (this.__nodeConfig.value = val)
|
||||
);
|
||||
this.__detachAnimation(this._animation);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__detachAnimation(animation) {
|
||||
animation && animation.__detach();
|
||||
if (this._animation === animation) {
|
||||
this._animation = null;
|
||||
}
|
||||
}
|
||||
|
||||
__attachAnimation(animation) {
|
||||
this.__detachAnimation(this._animation);
|
||||
this._animation = animation;
|
||||
}
|
||||
|
||||
__onEvaluate() {
|
||||
if (this.__inputNodes && this.__inputNodes.length) {
|
||||
this.__inputNodes.forEach(val);
|
||||
}
|
||||
return this._value + this._offset;
|
||||
}
|
||||
|
||||
_updateValue(value) {
|
||||
this._value = value;
|
||||
this.__forceUpdateCache(value);
|
||||
}
|
||||
import InternalAnimatedValue from './InternalAnimatedValue';
|
||||
import { evaluateOnce } from '../derived/evaluateOnce';
|
||||
|
||||
// Animated value wrapped with extra methods for omit cycle of dependencies
|
||||
export default class AnimatedValue extends InternalAnimatedValue {
|
||||
setValue(value) {
|
||||
this.__detachAnimation(this._animation);
|
||||
evaluateOnce(set(this, value), this);
|
||||
|
||||
54
src/core/InternalAnimatedValue.js
Normal file
54
src/core/InternalAnimatedValue.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import AnimatedNode from './AnimatedNode';
|
||||
import { val } from '../val';
|
||||
import ReanimatedModule from '../ReanimatedModule';
|
||||
|
||||
function sanitizeValue(value) {
|
||||
return value === null || value === undefined || typeof value === 'string'
|
||||
? value
|
||||
: Number(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class has been made internal in order to omit dependencies' cycles which
|
||||
* were caused by imperative setValue and interpolate – they are currently exposed with AnimatedValue.js
|
||||
*/
|
||||
export default class InternalAnimatedValue extends AnimatedNode {
|
||||
constructor(value) {
|
||||
super({ type: 'value', value: sanitizeValue(value) });
|
||||
this._startingValue = this._value = value;
|
||||
this._animation = null;
|
||||
}
|
||||
|
||||
__detach() {
|
||||
ReanimatedModule.getValue(
|
||||
this.__nodeID,
|
||||
val => (this.__nodeConfig.value = val)
|
||||
);
|
||||
this.__detachAnimation(this._animation);
|
||||
super.__detach();
|
||||
}
|
||||
|
||||
__detachAnimation(animation) {
|
||||
animation && animation.__detach();
|
||||
if (this._animation === animation) {
|
||||
this._animation = null;
|
||||
}
|
||||
}
|
||||
|
||||
__attachAnimation(animation) {
|
||||
this.__detachAnimation(this._animation);
|
||||
this._animation = animation;
|
||||
}
|
||||
|
||||
__onEvaluate() {
|
||||
if (this.__inputNodes && this.__inputNodes.length) {
|
||||
this.__inputNodes.forEach(val);
|
||||
}
|
||||
return this._value + this._offset;
|
||||
}
|
||||
|
||||
_updateValue(value) {
|
||||
this._value = value;
|
||||
this.__forceUpdateCache(value);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { set, add } from '../base';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
|
||||
export default function acc(v) {
|
||||
const acc = new AnimatedValue(0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cond, block, defined, sub, set } from '../base';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
|
||||
export default function diff(v) {
|
||||
const stash = new AnimatedValue(0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cond, defined, set, add } from '../base';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
import min from './min';
|
||||
import max from './max';
|
||||
import diff from './diff';
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import { call, always, cond, set } from '../base';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
import { createAnimatedSet as set } from '../core/AnimatedSet';
|
||||
import { createAnimatedCall as call } from '../core/AnimatedCall';
|
||||
import { createAnimatedAlways as always } from '../core/AnimatedAlways';
|
||||
import { createAnimatedCond as cond } from '../core/AnimatedCond';
|
||||
|
||||
/**
|
||||
* evaluate given node and notify children
|
||||
@@ -7,6 +10,7 @@ import { call, always, cond, set } from '../base';
|
||||
* @param input - nodes (or one node) representing values which states input for node.
|
||||
* @param callback - after callback
|
||||
*/
|
||||
|
||||
export function evaluateOnce(node, input = [], callback) {
|
||||
if (!Array.isArray(input)) {
|
||||
input = [input];
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
cond,
|
||||
lessThan,
|
||||
multiply,
|
||||
sub,
|
||||
add,
|
||||
divide,
|
||||
greaterThan,
|
||||
} from '../base';
|
||||
} from '../operators';
|
||||
|
||||
import { createAnimatedCond as cond } from '../core/AnimatedCond';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import AnimatedNode from '../core/AnimatedNode';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cond, lessThan } from '../base';
|
||||
import { adapt } from '../utils';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
export default function max(a, b) {
|
||||
a = adapt(a);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cond, lessThan } from '../base';
|
||||
import { adapt } from '../utils';
|
||||
import { adapt } from '../core/AnimatedBlock';
|
||||
|
||||
export default function min(a, b) {
|
||||
a = adapt(a);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { block, cond, defined, neq, not, set } from '../base';
|
||||
import AnimatedValue from '../core/AnimatedValue';
|
||||
import AnimatedValue from '../core/InternalAnimatedValue';
|
||||
|
||||
export default function onChange(value, action) {
|
||||
const prevValue = new AnimatedValue();
|
||||
|
||||
29
src/operators.js
Normal file
29
src/operators.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createAnimatedOperator } from './core/AnimatedOperator';
|
||||
|
||||
const operator = createAnimatedOperator;
|
||||
|
||||
export const add = operator('add');
|
||||
export const sub = operator('sub');
|
||||
export const multiply = operator('multiply');
|
||||
export const divide = operator('divide');
|
||||
export const pow = operator('pow');
|
||||
export const modulo = operator('modulo');
|
||||
export const sqrt = operator('sqrt');
|
||||
export const sin = operator('sin');
|
||||
export const cos = operator('cos');
|
||||
export const exp = operator('exp');
|
||||
export const round = operator('round');
|
||||
export const lessThan = operator('lessThan');
|
||||
export const eq = operator('eq');
|
||||
export const greaterThan = operator('greaterThan');
|
||||
export const lessOrEq = operator('lessOrEq');
|
||||
export const greaterOrEq = operator('greaterOrEq');
|
||||
export const neq = operator('neq');
|
||||
export const and = operator('and');
|
||||
export const or = operator('or');
|
||||
export const defined = operator('defined');
|
||||
export const not = operator('not');
|
||||
export const tan = operator('tan');
|
||||
export const acos = operator('acos');
|
||||
export const asin = operator('asin');
|
||||
export const atan = operator('atan');
|
||||
24
src/utils.js
24
src/utils.js
@@ -1,24 +0,0 @@
|
||||
import AnimatedBlock from './core/AnimatedBlock';
|
||||
import AnimatedNode from './core/AnimatedNode';
|
||||
import AnimatedValue from './core/AnimatedValue';
|
||||
|
||||
function nodify(v) {
|
||||
if (typeof v === 'object' && v.__isProxy) {
|
||||
if (!v.__val) {
|
||||
v.__val = new AnimatedValue(0);
|
||||
}
|
||||
return v.__val;
|
||||
}
|
||||
// TODO: cache some typical static values (e.g. 0, 1, -1)
|
||||
return v instanceof AnimatedNode ? v : new AnimatedValue(v);
|
||||
}
|
||||
|
||||
export function adapt(v) {
|
||||
return Array.isArray(v)
|
||||
? new AnimatedBlock(v.map(node => adapt(node)))
|
||||
: nodify(v);
|
||||
}
|
||||
|
||||
export function val(v) {
|
||||
return v && v.__getValue ? v.__getValue() : v || 0;
|
||||
}
|
||||
3
src/val.js
Normal file
3
src/val.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export function val(v) {
|
||||
return v && v.__getValue ? v.__getValue() : v || 0;
|
||||
}
|
||||
Reference in New Issue
Block a user