mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
[ReactNative] Remove POPAnimation
Summary: Thanks to @vjeux' work on Animated, we have transitioned away from POPAnimation entirely
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,148 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule Easing
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var bezier = require('bezier');
|
||||
|
||||
/**
|
||||
* This class implements common easing functions. The math is pretty obscure,
|
||||
* but this cool website has nice visual illustrations of what they represent:
|
||||
* http://xaedes.de/dev/transitions/
|
||||
*/
|
||||
class Easing {
|
||||
static step0(n) {
|
||||
return n > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static step1(n) {
|
||||
return n >= 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static linear(t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
static ease(t: number): number {
|
||||
return ease(t);
|
||||
}
|
||||
|
||||
static quad(t) {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
static cubic(t) {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
static poly(n) {
|
||||
return (t) => Math.pow(t, n);
|
||||
}
|
||||
|
||||
static sin(t) {
|
||||
return 1 - Math.cos(t * Math.PI / 2);
|
||||
}
|
||||
|
||||
static circle(t) {
|
||||
return 1 - Math.sqrt(1 - t * t);
|
||||
}
|
||||
|
||||
static exp(t) {
|
||||
return Math.pow(2, 10 * (t - 1));
|
||||
}
|
||||
|
||||
static elastic(a: number, p: number): (t: number) => number {
|
||||
var tau = Math.PI * 2;
|
||||
// flow isn't smart enough to figure out that s is always assigned to a
|
||||
// number before being used in the returned function
|
||||
var s: any;
|
||||
if (arguments.length < 2) {
|
||||
p = 0.45;
|
||||
}
|
||||
if (arguments.length) {
|
||||
s = p / tau * Math.asin(1 / a);
|
||||
} else {
|
||||
a = 1;
|
||||
s = p / 4;
|
||||
}
|
||||
return (t) => 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * tau / p);
|
||||
};
|
||||
|
||||
static back(s: number): (t: number) => number {
|
||||
if (s === undefined) {
|
||||
s = 1.70158;
|
||||
}
|
||||
return (t) => t * t * ((s + 1) * t - s);
|
||||
};
|
||||
|
||||
static bounce(t: number): number {
|
||||
if (t < 1 / 2.75) {
|
||||
return 7.5625 * t * t;
|
||||
}
|
||||
|
||||
if (t < 2 / 2.75) {
|
||||
t -= 1.5 / 2.75;
|
||||
return 7.5625 * t * t + 0.75;
|
||||
}
|
||||
|
||||
if (t < 2.5 / 2.75) {
|
||||
t -= 2.25 / 2.75;
|
||||
return 7.5625 * t * t + 0.9375;
|
||||
}
|
||||
|
||||
t -= 2.625 / 2.75;
|
||||
return 7.5625 * t * t + 0.984375;
|
||||
};
|
||||
|
||||
static bezier(
|
||||
x1: number,
|
||||
y1: number,
|
||||
x2: number,
|
||||
y2: number,
|
||||
epsilon?: ?number,
|
||||
): (t: number) => number {
|
||||
if (epsilon === undefined) {
|
||||
// epsilon determines the precision of the solved values
|
||||
// a good approximation is:
|
||||
var duration = 500; // duration of animation in milliseconds.
|
||||
epsilon = (1000 / 60 / duration) / 4;
|
||||
}
|
||||
|
||||
return bezier(x1, y1, x2, y2, epsilon);
|
||||
}
|
||||
|
||||
static in(
|
||||
easing: (t: number) => number,
|
||||
): (t: number) => number {
|
||||
return easing;
|
||||
}
|
||||
|
||||
static out(
|
||||
easing: (t: number) => number,
|
||||
): (t: number) => number {
|
||||
return (t) => 1 - easing(1 - t);
|
||||
}
|
||||
|
||||
static inOut(
|
||||
easing: (t: number) => number,
|
||||
): (t: number) => number {
|
||||
return (t) => {
|
||||
if (t < 0.5) {
|
||||
return easing(t * 2) / 2;
|
||||
}
|
||||
return 1 - easing((1 - t) * 2) / 2;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var ease = Easing.bezier(0.42, 0, 1, 1);
|
||||
|
||||
module.exports = Easing;
|
||||
@@ -1,265 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule Interpolation
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
// TODO(#7644673): fix this hack once github jest actually checks invariants
|
||||
var invariant = function(condition, message) {
|
||||
if (!condition) {
|
||||
var error = new Error(message);
|
||||
(error: any).framesToPop = 1; // $FlowIssue
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
type ExtrapolateType = 'extend' | 'identity' | 'clamp';
|
||||
|
||||
// $FlowFixMe D2163827
|
||||
export type InterpolationConfigType = {
|
||||
inputRange: Array<number>;
|
||||
outputRange: (Array<number> | Array<string>);
|
||||
easing?: ((input: number) => number);
|
||||
extrapolate?: ExtrapolateType;
|
||||
extrapolateLeft?: ExtrapolateType;
|
||||
extrapolateRight?: ExtrapolateType;
|
||||
};
|
||||
|
||||
var linear = (t) => t;
|
||||
|
||||
/**
|
||||
* Very handy helper to map input ranges to output ranges with an easing
|
||||
* function and custom behavior outside of the ranges.
|
||||
*/
|
||||
class Interpolation {
|
||||
static create(config: InterpolationConfigType): (input: number) => number | string {
|
||||
|
||||
if (config.outputRange && typeof config.outputRange[0] === 'string') {
|
||||
return createInterpolationFromStringOutputRange(config);
|
||||
}
|
||||
|
||||
var outputRange: Array<number> = (config.outputRange: any);
|
||||
checkInfiniteRange('outputRange', outputRange);
|
||||
|
||||
var inputRange = config.inputRange;
|
||||
checkInfiniteRange('inputRange', inputRange);
|
||||
checkValidInputRange(inputRange);
|
||||
|
||||
invariant(
|
||||
inputRange.length === outputRange.length,
|
||||
'inputRange (' + inputRange.length + ') and outputRange (' +
|
||||
outputRange.length + ') must have the same length'
|
||||
);
|
||||
|
||||
var easing = config.easing || linear;
|
||||
|
||||
var extrapolateLeft: ExtrapolateType = 'extend';
|
||||
if (config.extrapolateLeft !== undefined) {
|
||||
extrapolateLeft = config.extrapolateLeft;
|
||||
} else if (config.extrapolate !== undefined) {
|
||||
extrapolateLeft = config.extrapolate;
|
||||
}
|
||||
|
||||
var extrapolateRight: ExtrapolateType = 'extend';
|
||||
if (config.extrapolateRight !== undefined) {
|
||||
extrapolateRight = config.extrapolateRight;
|
||||
} else if (config.extrapolate !== undefined) {
|
||||
extrapolateRight = config.extrapolate;
|
||||
}
|
||||
|
||||
return (input) => {
|
||||
invariant(
|
||||
typeof input === 'number',
|
||||
'Cannot interpolation an input which is not a number'
|
||||
);
|
||||
|
||||
var range = findRange(input, inputRange);
|
||||
return interpolate(
|
||||
input,
|
||||
inputRange[range],
|
||||
inputRange[range + 1],
|
||||
outputRange[range],
|
||||
outputRange[range + 1],
|
||||
easing,
|
||||
extrapolateLeft,
|
||||
extrapolateRight,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function interpolate(
|
||||
input: number,
|
||||
inputMin: number,
|
||||
inputMax: number,
|
||||
outputMin: number,
|
||||
outputMax: number,
|
||||
easing: ((input: number) => number),
|
||||
extrapolateLeft: ExtrapolateType,
|
||||
extrapolateRight: ExtrapolateType,
|
||||
) {
|
||||
var result = input;
|
||||
|
||||
// Extrapolate
|
||||
if (result < inputMin) {
|
||||
if (extrapolateLeft === 'identity') {
|
||||
return result;
|
||||
} else if (extrapolateLeft === 'clamp') {
|
||||
result = inputMin;
|
||||
} else if (extrapolateLeft === 'extend') {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (result > inputMax) {
|
||||
if (extrapolateRight === 'identity') {
|
||||
return result;
|
||||
} else if (extrapolateRight === 'clamp') {
|
||||
result = inputMax;
|
||||
} else if (extrapolateRight === 'extend') {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (outputMin === outputMax) {
|
||||
return outputMin;
|
||||
}
|
||||
|
||||
if (inputMin === inputMax) {
|
||||
if (input <= inputMin) {
|
||||
return outputMin;
|
||||
}
|
||||
return outputMax;
|
||||
}
|
||||
|
||||
// Input Range
|
||||
if (inputMin === -Infinity) {
|
||||
result = -result;
|
||||
} else if (inputMax === Infinity) {
|
||||
result = result - inputMin;
|
||||
} else {
|
||||
result = (result - inputMin) / (inputMax - inputMin);
|
||||
}
|
||||
|
||||
// Easing
|
||||
result = easing(result);
|
||||
|
||||
// Output Range
|
||||
if (outputMin === -Infinity) {
|
||||
result = -result;
|
||||
} else if (outputMax === Infinity) {
|
||||
result = result + outputMin;
|
||||
} else {
|
||||
result = result * (outputMax - outputMin) + outputMin;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var stringShapeRegex = /[0-9\.-]+/g;
|
||||
|
||||
/**
|
||||
* Supports string shapes by extracting numbers so new values can be computed,
|
||||
* and recombines those values into new strings of the same shape. Supports
|
||||
* things like:
|
||||
*
|
||||
* rgba(123, 42, 99, 0.36) // colors
|
||||
* -45deg // values with units
|
||||
*/
|
||||
function createInterpolationFromStringOutputRange(
|
||||
config: InterpolationConfigType,
|
||||
): (input: number) => string {
|
||||
var outputRange: Array<string> = (config.outputRange: any);
|
||||
invariant(outputRange.length >= 2, 'Bad output range');
|
||||
checkPattern(outputRange);
|
||||
|
||||
// ['rgba(0, 100, 200, 0)', 'rgba(50, 150, 250, 0.5)']
|
||||
// ->
|
||||
// [
|
||||
// [0, 50],
|
||||
// [100, 150],
|
||||
// [200, 250],
|
||||
// [0, 0.5],
|
||||
// ]
|
||||
var outputRanges = outputRange[0].match(stringShapeRegex).map(() => []);
|
||||
outputRange.forEach(value => {
|
||||
value.match(stringShapeRegex).forEach((number, i) => {
|
||||
outputRanges[i].push(+number);
|
||||
});
|
||||
});
|
||||
|
||||
var interpolations = outputRange[0].match(stringShapeRegex).map((value, i) => {
|
||||
return Interpolation.create({
|
||||
...config,
|
||||
outputRange: outputRanges[i],
|
||||
});
|
||||
});
|
||||
|
||||
return (input) => {
|
||||
var i = 0;
|
||||
// 'rgba(0, 100, 200, 0)'
|
||||
// ->
|
||||
// 'rgba(${interpolations[0](input)}, ${interpolations[1](input)}, ...'
|
||||
return outputRange[0].replace(stringShapeRegex, () => {
|
||||
return String(interpolations[i++](input));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function checkPattern(arr: Array<string>) {
|
||||
var pattern = arr[0].replace(stringShapeRegex, '');
|
||||
for (var i = 1; i < arr.length; ++i) {
|
||||
invariant(
|
||||
pattern === arr[i].replace(stringShapeRegex, ''),
|
||||
'invalid pattern ' + arr[0] + ' and ' + arr[i],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function findRange(input: number, inputRange: Array<number>) {
|
||||
for (var i = 1; i < inputRange.length - 1; ++i) {
|
||||
if (inputRange[i] >= input) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
function checkValidInputRange(arr: Array<number>) {
|
||||
invariant(arr.length >= 2, 'inputRange must have at least 2 elements');
|
||||
for (var i = 1; i < arr.length; ++i) {
|
||||
invariant(
|
||||
arr[i] >= arr[i - 1],
|
||||
/* $FlowFixMe(>=0.13.0) - In the addition expression below this comment,
|
||||
* one or both of the operands may be something that doesn't cleanly
|
||||
* convert to a string, like undefined, null, and object, etc. If you really
|
||||
* mean this implicit string conversion, you can do something like
|
||||
* String(myThing)
|
||||
*/
|
||||
'inputRange must be monotonically increasing ' + arr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function checkInfiniteRange(name: string, arr: Array<number>) {
|
||||
invariant(arr.length >= 2, name + ' must have at least 2 elements');
|
||||
invariant(
|
||||
arr.length !== 2 || arr[0] !== -Infinity || arr[1] !== Infinity,
|
||||
/* $FlowFixMe(>=0.13.0) - In the addition expression below this comment,
|
||||
* one or both of the operands may be something that doesn't cleanly convert
|
||||
* to a string, like undefined, null, and object, etc. If you really mean
|
||||
* this implicit string conversion, you can do something like
|
||||
* String(myThing)
|
||||
*/
|
||||
name + 'cannot be ]-infinity;+infinity[ ' + arr
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = Interpolation;
|
||||
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule SpringConfig
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
type SpringConfigType = {
|
||||
tension: number,
|
||||
friction: number,
|
||||
};
|
||||
|
||||
function tensionFromOrigamiValue(oValue) {
|
||||
return (oValue - 30) * 3.62 + 194;
|
||||
}
|
||||
|
||||
function frictionFromOrigamiValue(oValue) {
|
||||
return (oValue - 8) * 3 + 25;
|
||||
}
|
||||
|
||||
function fromOrigamiTensionAndFriction(
|
||||
tension: number,
|
||||
friction: number,
|
||||
): SpringConfigType {
|
||||
return {
|
||||
tension: tensionFromOrigamiValue(tension),
|
||||
friction: frictionFromOrigamiValue(friction)
|
||||
};
|
||||
}
|
||||
|
||||
function fromBouncinessAndSpeed(
|
||||
bounciness: number,
|
||||
speed: number,
|
||||
): SpringConfigType {
|
||||
function normalize(value, startValue, endValue) {
|
||||
return (value - startValue) / (endValue - startValue);
|
||||
}
|
||||
|
||||
function projectNormal(n, start, end) {
|
||||
return start + (n * (end - start));
|
||||
}
|
||||
|
||||
function linearInterpolation(t, start, end) {
|
||||
return t * end + (1 - t) * start;
|
||||
}
|
||||
|
||||
function quadraticOutInterpolation(t, start, end) {
|
||||
return linearInterpolation(2 * t - t * t, start, end);
|
||||
}
|
||||
|
||||
function b3Friction1(x) {
|
||||
return (0.0007 * Math.pow(x, 3)) -
|
||||
(0.031 * Math.pow(x, 2)) + 0.64 * x + 1.28;
|
||||
}
|
||||
|
||||
function b3Friction2(x) {
|
||||
return (0.000044 * Math.pow(x, 3)) -
|
||||
(0.006 * Math.pow(x, 2)) + 0.36 * x + 2;
|
||||
}
|
||||
|
||||
function b3Friction3(x) {
|
||||
return (0.00000045 * Math.pow(x, 3)) -
|
||||
(0.000332 * Math.pow(x, 2)) + 0.1078 * x + 5.84;
|
||||
}
|
||||
|
||||
function b3Nobounce(tension) {
|
||||
if (tension <= 18) {
|
||||
return b3Friction1(tension);
|
||||
} else if (tension > 18 && tension <= 44) {
|
||||
return b3Friction2(tension);
|
||||
} else {
|
||||
return b3Friction3(tension);
|
||||
}
|
||||
}
|
||||
|
||||
var b = normalize(bounciness / 1.7, 0, 20);
|
||||
b = projectNormal(b, 0, 0.8);
|
||||
var s = normalize(speed / 1.7, 0, 20);
|
||||
var bouncyTension = projectNormal(s, 0.5, 200);
|
||||
var bouncyFriction = quadraticOutInterpolation(
|
||||
b,
|
||||
b3Nobounce(bouncyTension),
|
||||
0.01
|
||||
);
|
||||
|
||||
return {
|
||||
tension: tensionFromOrigamiValue(bouncyTension),
|
||||
friction: frictionFromOrigamiValue(bouncyFriction)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fromOrigamiTensionAndFriction,
|
||||
fromBouncinessAndSpeed,
|
||||
};
|
||||
@@ -1,516 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest
|
||||
.autoMockOff()
|
||||
.setMock('Text', {})
|
||||
.setMock('View', {})
|
||||
.setMock('Image', {})
|
||||
.setMock('React', {Component: class {}});
|
||||
|
||||
var Animated = require('Animated');
|
||||
|
||||
describe('Animated', () => {
|
||||
it('works end to end', () => {
|
||||
var anim = new Animated.Value(0);
|
||||
|
||||
var callback = jest.genMockFunction();
|
||||
|
||||
var node = new Animated.__PropsOnlyForTests({
|
||||
style: {
|
||||
backgroundColor: 'red',
|
||||
opacity: anim,
|
||||
transform: [
|
||||
{translateX: anim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [100, 200],
|
||||
})},
|
||||
{scale: anim},
|
||||
]
|
||||
}
|
||||
}, callback);
|
||||
|
||||
expect(anim.__getChildren().length).toBe(3);
|
||||
|
||||
expect(node.__getValue()).toEqual({
|
||||
style: {
|
||||
backgroundColor: 'red',
|
||||
opacity: 0,
|
||||
transform: [
|
||||
{translateX: 100},
|
||||
{scale: 0},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
anim.setValue(0.5);
|
||||
|
||||
expect(callback).toBeCalled();
|
||||
|
||||
expect(node.__getValue()).toEqual({
|
||||
style: {
|
||||
backgroundColor: 'red',
|
||||
opacity: 0.5,
|
||||
transform: [
|
||||
{translateX: 150},
|
||||
{scale: 0.5},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
node.__detach();
|
||||
expect(anim.__getChildren().length).toBe(0);
|
||||
|
||||
anim.setValue(1);
|
||||
expect(callback.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('does not detach on updates', () => {
|
||||
var anim = new Animated.Value(0);
|
||||
anim.__detach = jest.genMockFunction();
|
||||
|
||||
var c = new Animated.View();
|
||||
c.props = {
|
||||
style: {
|
||||
opacity: anim,
|
||||
},
|
||||
};
|
||||
c.componentWillMount();
|
||||
|
||||
expect(anim.__detach).not.toBeCalled();
|
||||
c.componentWillReceiveProps({
|
||||
style: {
|
||||
opacity: anim,
|
||||
},
|
||||
});
|
||||
expect(anim.__detach).not.toBeCalled();
|
||||
|
||||
c.componentWillUnmount();
|
||||
expect(anim.__detach).toBeCalled();
|
||||
});
|
||||
|
||||
|
||||
it('stops animation when detached', () => {
|
||||
// jest environment doesn't have requestAnimationFrame :(
|
||||
window.requestAnimationFrame = jest.genMockFunction();
|
||||
window.cancelAnimationFrame = jest.genMockFunction();
|
||||
|
||||
var anim = new Animated.Value(0);
|
||||
var callback = jest.genMockFunction();
|
||||
|
||||
var c = new Animated.View();
|
||||
c.props = {
|
||||
style: {
|
||||
opacity: anim,
|
||||
},
|
||||
};
|
||||
c.componentWillMount();
|
||||
|
||||
Animated.timing(anim, {toValue: 10, duration: 1000}).start(callback);
|
||||
|
||||
c.componentWillUnmount();
|
||||
|
||||
expect(callback).toBeCalledWith({finished: false});
|
||||
expect(callback).toBeCalledWith({finished: false});
|
||||
});
|
||||
|
||||
it('triggers callback when spring is at rest', () => {
|
||||
var anim = new Animated.Value(0);
|
||||
var callback = jest.genMockFunction();
|
||||
Animated.spring(anim, {toValue: 0, velocity: 0}).start(callback);
|
||||
expect(callback).toBeCalled();
|
||||
});
|
||||
|
||||
it('send toValue when a spring stops', () => {
|
||||
var anim = new Animated.Value(0);
|
||||
var listener = jest.genMockFunction();
|
||||
anim.addListener(listener);
|
||||
Animated.spring(anim, {toValue: 15}).start();
|
||||
jest.runAllTimers();
|
||||
var lastValue = listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
||||
expect(lastValue).not.toBe(15);
|
||||
expect(lastValue).toBeCloseTo(15);
|
||||
expect(anim.__getValue()).toBe(15);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('Animated Sequence', () => {
|
||||
|
||||
it('works with an empty sequence', () => {
|
||||
var cb = jest.genMockFunction();
|
||||
Animated.sequence([]).start(cb);
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
|
||||
it('sequences well', () => {
|
||||
var anim1 = {start: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
var seq = Animated.sequence([anim1, anim2]);
|
||||
|
||||
expect(anim1.start).not.toBeCalled();
|
||||
expect(anim2.start).not.toBeCalled();
|
||||
|
||||
seq.start(cb);
|
||||
|
||||
expect(anim1.start).toBeCalled();
|
||||
expect(anim2.start).not.toBeCalled();
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: true});
|
||||
|
||||
expect(anim2.start).toBeCalled();
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim2.start.mock.calls[0][0]({finished: true});
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
|
||||
it('supports interrupting sequence', () => {
|
||||
var anim1 = {start: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
Animated.sequence([anim1, anim2]).start(cb);
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: false});
|
||||
|
||||
expect(anim1.start).toBeCalled();
|
||||
expect(anim2.start).not.toBeCalled();
|
||||
expect(cb).toBeCalledWith({finished: false});
|
||||
});
|
||||
|
||||
it('supports stopping sequence', () => {
|
||||
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
var seq = Animated.sequence([anim1, anim2]);
|
||||
seq.start(cb);
|
||||
seq.stop();
|
||||
|
||||
expect(anim1.stop).toBeCalled();
|
||||
expect(anim2.stop).not.toBeCalled();
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: false});
|
||||
|
||||
expect(cb).toBeCalledWith({finished: false});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('Animated Parallel', () => {
|
||||
|
||||
it('works with an empty parallel', () => {
|
||||
var cb = jest.genMockFunction();
|
||||
Animated.parallel([]).start(cb);
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
|
||||
it('works with an empty element in array', () => {
|
||||
var anim1 = {start: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
Animated.parallel([null, anim1]).start(cb);
|
||||
|
||||
expect(anim1.start).toBeCalled();
|
||||
anim1.start.mock.calls[0][0]({finished: true});
|
||||
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
|
||||
it('parellelizes well', () => {
|
||||
var anim1 = {start: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
var par = Animated.parallel([anim1, anim2]);
|
||||
|
||||
expect(anim1.start).not.toBeCalled();
|
||||
expect(anim2.start).not.toBeCalled();
|
||||
|
||||
par.start(cb);
|
||||
|
||||
expect(anim1.start).toBeCalled();
|
||||
expect(anim2.start).toBeCalled();
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: true});
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim2.start.mock.calls[0][0]({finished: true});
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
|
||||
it('supports stopping parallel', () => {
|
||||
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
var seq = Animated.parallel([anim1, anim2]);
|
||||
seq.start(cb);
|
||||
seq.stop();
|
||||
|
||||
expect(anim1.stop).toBeCalled();
|
||||
expect(anim2.stop).toBeCalled();
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: false});
|
||||
expect(cb).not.toBeCalled();
|
||||
|
||||
anim2.start.mock.calls[0][0]({finished: false});
|
||||
expect(cb).toBeCalledWith({finished: false});
|
||||
});
|
||||
|
||||
|
||||
it('does not call stop more than once when stopping', () => {
|
||||
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var anim3 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
|
||||
var seq = Animated.parallel([anim1, anim2, anim3]);
|
||||
seq.start(cb);
|
||||
|
||||
anim1.start.mock.calls[0][0]({finished: false});
|
||||
|
||||
expect(anim1.stop.mock.calls.length).toBe(0);
|
||||
expect(anim2.stop.mock.calls.length).toBe(1);
|
||||
expect(anim3.stop.mock.calls.length).toBe(1);
|
||||
|
||||
anim2.start.mock.calls[0][0]({finished: false});
|
||||
|
||||
expect(anim1.stop.mock.calls.length).toBe(0);
|
||||
expect(anim2.stop.mock.calls.length).toBe(1);
|
||||
expect(anim3.stop.mock.calls.length).toBe(1);
|
||||
|
||||
anim3.start.mock.calls[0][0]({finished: false});
|
||||
|
||||
expect(anim1.stop.mock.calls.length).toBe(0);
|
||||
expect(anim2.stop.mock.calls.length).toBe(1);
|
||||
expect(anim3.stop.mock.calls.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated delays', () => {
|
||||
it('should call anim after delay in sequence', () => {
|
||||
var anim = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
||||
var cb = jest.genMockFunction();
|
||||
Animated.sequence([
|
||||
Animated.delay(1000),
|
||||
anim,
|
||||
]).start(cb);
|
||||
jest.runAllTimers();
|
||||
expect(anim.start.mock.calls.length).toBe(1);
|
||||
expect(cb).not.toBeCalled();
|
||||
anim.start.mock.calls[0][0]({finished: true});
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
it('should run stagger to end', () => {
|
||||
var cb = jest.genMockFunction();
|
||||
Animated.stagger(1000, [
|
||||
Animated.delay(1000),
|
||||
Animated.delay(1000),
|
||||
Animated.delay(1000),
|
||||
]).start(cb);
|
||||
jest.runAllTimers();
|
||||
expect(cb).toBeCalledWith({finished: true});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated Events', () => {
|
||||
it('should map events', () => {
|
||||
var value = new Animated.Value(0);
|
||||
var handler = Animated.event(
|
||||
[null, {state: {foo: value}}],
|
||||
);
|
||||
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
|
||||
expect(value.__getValue()).toBe(42);
|
||||
});
|
||||
it('should call listeners', () => {
|
||||
var value = new Animated.Value(0);
|
||||
var listener = jest.genMockFunction();
|
||||
var handler = Animated.event(
|
||||
[{foo: value}],
|
||||
{listener},
|
||||
);
|
||||
handler({foo: 42});
|
||||
expect(value.__getValue()).toBe(42);
|
||||
expect(listener.mock.calls.length).toBe(1);
|
||||
expect(listener).toBeCalledWith({foo: 42});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated Tracking', () => {
|
||||
it('should track values', () => {
|
||||
var value1 = new Animated.Value(0);
|
||||
var value2 = new Animated.Value(0);
|
||||
Animated.timing(value2, {
|
||||
toValue: value1,
|
||||
duration: 0,
|
||||
}).start();
|
||||
value1.setValue(42);
|
||||
expect(value2.__getValue()).toBe(42);
|
||||
value1.setValue(7);
|
||||
expect(value2.__getValue()).toBe(7);
|
||||
});
|
||||
|
||||
it('should track interpolated values', () => {
|
||||
var value1 = new Animated.Value(0);
|
||||
var value2 = new Animated.Value(0);
|
||||
Animated.timing(value2, {
|
||||
toValue: value1.interpolate({
|
||||
inputRange: [0, 2],
|
||||
outputRange: [0, 1]
|
||||
}),
|
||||
duration: 0,
|
||||
}).start();
|
||||
value1.setValue(42);
|
||||
expect(value2.__getValue()).toBe(42 / 2);
|
||||
});
|
||||
|
||||
it('should stop tracking when animated', () => {
|
||||
var value1 = new Animated.Value(0);
|
||||
var value2 = new Animated.Value(0);
|
||||
Animated.timing(value2, {
|
||||
toValue: value1,
|
||||
duration: 0,
|
||||
}).start();
|
||||
value1.setValue(42);
|
||||
expect(value2.__getValue()).toBe(42);
|
||||
Animated.timing(value2, {
|
||||
toValue: 7,
|
||||
duration: 0,
|
||||
}).start();
|
||||
value1.setValue(1492);
|
||||
expect(value2.__getValue()).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated Vectors', () => {
|
||||
it('should animate vectors', () => {
|
||||
var vec = new Animated.ValueXY();
|
||||
|
||||
var callback = jest.genMockFunction();
|
||||
|
||||
var node = new Animated.__PropsOnlyForTests({
|
||||
style: {
|
||||
opacity: vec.x.interpolate({
|
||||
inputRange: [0, 42],
|
||||
outputRange: [0.2, 0.8],
|
||||
}),
|
||||
transform: vec.getTranslateTransform(),
|
||||
...vec.getLayout(),
|
||||
}
|
||||
}, callback);
|
||||
|
||||
expect(node.__getValue()).toEqual({
|
||||
style: {
|
||||
opacity: 0.2,
|
||||
transform: [
|
||||
{translateX: 0},
|
||||
{translateY: 0},
|
||||
],
|
||||
left: 0,
|
||||
top: 0,
|
||||
},
|
||||
});
|
||||
|
||||
vec.setValue({x: 42, y: 1492});
|
||||
|
||||
expect(callback.mock.calls.length).toBe(2); // once each for x, y
|
||||
|
||||
expect(node.__getValue()).toEqual({
|
||||
style: {
|
||||
opacity: 0.8,
|
||||
transform: [
|
||||
{translateX: 42},
|
||||
{translateY: 1492},
|
||||
],
|
||||
left: 42,
|
||||
top: 1492,
|
||||
},
|
||||
});
|
||||
|
||||
node.__detach();
|
||||
|
||||
vec.setValue({x: 1, y: 1});
|
||||
expect(callback.mock.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should track vectors', () => {
|
||||
var value1 = new Animated.ValueXY();
|
||||
var value2 = new Animated.ValueXY();
|
||||
Animated.timing(value2, {
|
||||
toValue: value1,
|
||||
duration: 0,
|
||||
}).start();
|
||||
value1.setValue({x: 42, y: 1492});
|
||||
expect(value2.__getValue()).toEqual({x: 42, y: 1492});
|
||||
|
||||
// Make sure tracking keeps working (see stopTogether in ParallelConfig used
|
||||
// by maybeVectorAnim).
|
||||
value1.setValue({x: 3, y: 4});
|
||||
expect(value2.__getValue()).toEqual({x: 3, y: 4});
|
||||
});
|
||||
|
||||
it('should track with springs', () => {
|
||||
var value1 = new Animated.ValueXY();
|
||||
var value2 = new Animated.ValueXY();
|
||||
Animated.spring(value2, {
|
||||
toValue: value1,
|
||||
tension: 3000, // faster spring for faster test
|
||||
friction: 60,
|
||||
}).start();
|
||||
value1.setValue({x: 1, y: 1});
|
||||
jest.runAllTimers();
|
||||
expect(Math.round(value2.__getValue().x)).toEqual(1);
|
||||
expect(Math.round(value2.__getValue().y)).toEqual(1);
|
||||
value1.setValue({x: 2, y: 2});
|
||||
jest.runAllTimers();
|
||||
expect(Math.round(value2.__getValue().x)).toEqual(2);
|
||||
expect(Math.round(value2.__getValue().y)).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animated Listeners', () => {
|
||||
it('should get updates', () => {
|
||||
var value1 = new Animated.Value(0);
|
||||
var listener = jest.genMockFunction();
|
||||
var id = value1.addListener(listener);
|
||||
value1.setValue(42);
|
||||
expect(listener.mock.calls.length).toBe(1);
|
||||
expect(listener).toBeCalledWith({value: 42});
|
||||
expect(value1.__getValue()).toBe(42);
|
||||
value1.setValue(7);
|
||||
expect(listener.mock.calls.length).toBe(2);
|
||||
expect(listener).toBeCalledWith({value: 7});
|
||||
expect(value1.__getValue()).toBe(7);
|
||||
value1.removeListener(id);
|
||||
value1.setValue(1492);
|
||||
expect(listener.mock.calls.length).toBe(2);
|
||||
expect(value1.__getValue()).toBe(1492);
|
||||
});
|
||||
|
||||
it('should removeAll', () => {
|
||||
var value1 = new Animated.Value(0);
|
||||
var listener = jest.genMockFunction();
|
||||
[1,2,3,4].forEach(() => value1.addListener(listener));
|
||||
value1.setValue(42);
|
||||
expect(listener.mock.calls.length).toBe(4);
|
||||
expect(listener).toBeCalledWith({value: 42});
|
||||
value1.removeAllListeners();
|
||||
value1.setValue(7);
|
||||
expect(listener.mock.calls.length).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -1,119 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest.dontMock('Easing');
|
||||
|
||||
var Easing = require('Easing');
|
||||
describe('Easing', () => {
|
||||
it('should work with linear', () => {
|
||||
var easing = Easing.linear;
|
||||
|
||||
expect(easing(0)).toBe(0);
|
||||
expect(easing(0.5)).toBe(0.5);
|
||||
expect(easing(0.8)).toBe(0.8);
|
||||
expect(easing(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with ease in linear', () => {
|
||||
var easing = Easing.in(Easing.linear);
|
||||
expect(easing(0)).toBe(0);
|
||||
expect(easing(0.5)).toBe(0.5);
|
||||
expect(easing(0.8)).toBe(0.8);
|
||||
expect(easing(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with easy out linear', () => {
|
||||
var easing = Easing.out(Easing.linear);
|
||||
expect(easing(0)).toBe(0);
|
||||
expect(easing(0.5)).toBe(0.5);
|
||||
expect(easing(0.6)).toBe(0.6);
|
||||
expect(easing(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with ease in quad', () => {
|
||||
function easeInQuad(t) {
|
||||
return t * t;
|
||||
}
|
||||
var easing = Easing.in(Easing.quad);
|
||||
for (var t = -0.5; t < 1.5; t += 0.1) {
|
||||
expect(easing(t)).toBe(easeInQuad(t));
|
||||
}
|
||||
});
|
||||
|
||||
it('should work with ease out quad', () => {
|
||||
function easeOutQuad(t) {
|
||||
return -t * (t - 2);
|
||||
}
|
||||
var easing = Easing.out(Easing.quad);
|
||||
for (var t = 0; t <= 1; t += 0.1) {
|
||||
expect(easing(1)).toBe(easeOutQuad(1));
|
||||
}
|
||||
});
|
||||
|
||||
it('should work with ease in-out quad', () => {
|
||||
function easeInOutQuad(t) {
|
||||
t = t * 2;
|
||||
if (t < 1) {
|
||||
return 0.5 * t * t;
|
||||
}
|
||||
return -((t - 1) * (t - 3) - 1) / 2;
|
||||
}
|
||||
var easing = Easing.inOut(Easing.quad);
|
||||
for (var t = -0.5; t < 1.5; t += 0.1) {
|
||||
expect(easing(t)).toBeCloseTo(easeInOutQuad(t), 4);
|
||||
}
|
||||
});
|
||||
|
||||
function sampleEasingFunction(easing) {
|
||||
var DURATION = 300;
|
||||
var tickCount = Math.round(DURATION * 60 / 1000);
|
||||
var samples = [];
|
||||
for (var i = 0; i <= tickCount; i++) {
|
||||
samples.push(easing(i / tickCount));
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
var Samples = {
|
||||
in_quad: [0,0.0030864197530864196,0.012345679012345678,0.027777777777777776,0.04938271604938271,0.0771604938271605,0.1111111111111111,0.15123456790123457,0.19753086419753085,0.25,0.308641975308642,0.37345679012345684,0.4444444444444444,0.5216049382716049,0.6049382716049383,0.6944444444444445,0.7901234567901234,0.8919753086419753,1],
|
||||
out_quad: [0,0.10802469135802469,0.20987654320987653,0.3055555555555555,0.3950617283950617,0.47839506172839513,0.5555555555555556,0.6265432098765432,0.691358024691358,0.75,0.8024691358024691,0.8487654320987654,0.888888888888889,0.9228395061728394,0.9506172839506174,0.9722222222222221,0.9876543209876543,0.9969135802469136,1],
|
||||
inOut_quad: [0,0.006172839506172839,0.024691358024691357,0.05555555555555555,0.09876543209876543,0.154320987654321,0.2222222222222222,0.30246913580246915,0.3950617283950617,0.5,0.6049382716049383,0.697530864197531,0.7777777777777777,0.845679012345679,0.9012345679012346,0.9444444444444444,0.9753086419753086,0.9938271604938271,1],
|
||||
in_cubic: [0,0.00017146776406035664,0.0013717421124828531,0.004629629629629629,0.010973936899862825,0.021433470507544586,0.037037037037037035,0.05881344307270234,0.0877914951989026,0.125,0.1714677640603567,0.22822359396433475,0.2962962962962963,0.37671467764060357,0.4705075445816187,0.5787037037037038,0.7023319615912208,0.8424211248285322,1],
|
||||
out_cubic: [0,0.15757887517146785,0.2976680384087792,0.42129629629629617,0.5294924554183813,0.6232853223593964,0.7037037037037036,0.7717764060356652,0.8285322359396433,0.875,0.9122085048010974,0.9411865569272977,0.9629629629629629,0.9785665294924554,0.9890260631001372,0.9953703703703703,0.9986282578875172,0.9998285322359396,1],
|
||||
inOut_cubic: [0,0.0006858710562414266,0.0054869684499314125,0.018518518518518517,0.0438957475994513,0.08573388203017834,0.14814814814814814,0.23525377229080935,0.3511659807956104,0.5,0.6488340192043895,0.7647462277091908,0.8518518518518519,0.9142661179698217,0.9561042524005487,0.9814814814814815,0.9945130315500685,0.9993141289437586,1],
|
||||
in_sin: [0,0.003805301908254455,0.01519224698779198,0.03407417371093169,0.06030737921409157,0.09369221296335006,0.1339745962155613,0.1808479557110082,0.233955556881022,0.2928932188134524,0.35721239031346064,0.42642356364895384,0.4999999999999999,0.5773817382593005,0.6579798566743311,0.7411809548974793,0.8263518223330696,0.9128442572523416,0.9999999999999999],
|
||||
out_sin: [0,0.08715574274765817,0.17364817766693033,0.25881904510252074,0.3420201433256687,0.42261826174069944,0.49999999999999994,0.573576436351046,0.6427876096865393,0.7071067811865475,0.766044443118978,0.8191520442889918,0.8660254037844386,0.9063077870366499,0.9396926207859083,0.9659258262890683,0.984807753012208,0.9961946980917455,1],
|
||||
inOut_sin: [0,0.00759612349389599,0.030153689607045786,0.06698729810778065,0.116977778440511,0.17860619515673032,0.24999999999999994,0.32898992833716556,0.4131759111665348,0.49999999999999994,0.5868240888334652,0.6710100716628343,0.7499999999999999,0.8213938048432696,0.883022221559489,0.9330127018922194,0.9698463103929542,0.9924038765061041,1],
|
||||
in_exp: [0,0.0014352875901128893,0.002109491677524035,0.0031003926796253885,0.004556754060844206,0.006697218616039631,0.009843133202303688,0.014466792379488908,0.021262343752724643,0.03125,0.045929202883612456,0.06750373368076916,0.09921256574801243,0.1458161299470146,0.2143109957132682,0.31498026247371835,0.46293735614364506,0.6803950000871883,1],
|
||||
out_exp: [0,0.31960499991281155,0.5370626438563548,0.6850197375262816,0.7856890042867318,0.8541838700529854,0.9007874342519875,0.9324962663192309,0.9540707971163875,0.96875,0.9787376562472754,0.9855332076205111,0.9901568667976963,0.9933027813839603,0.9954432459391558,0.9968996073203746,0.9978905083224759,0.9985647124098871,1],
|
||||
inOut_exp: [0,0.0010547458387620175,0.002278377030422103,0.004921566601151844,0.010631171876362321,0.022964601441806228,0.049606282874006216,0.1071554978566341,0.23146867807182253,0.5,0.7685313219281775,0.892844502143366,0.9503937171259937,0.9770353985581938,0.9893688281236377,0.9950784333988482,0.9977216229695779,0.998945254161238,1],
|
||||
in_circle: [0,0.0015444024660317135,0.006192010000093506,0.013986702816730645,0.025003956956430873,0.03935464078941209,0.057190958417936644,0.07871533601238889,0.10419358352238339,0.1339745962155614,0.1685205807169019,0.20845517506805522,0.2546440075000701,0.3083389112228482,0.37146063894529113,0.4472292016074334,0.5418771527091488,0.6713289009389102,1],
|
||||
out_circle: [0,0.3286710990610898,0.45812284729085123,0.5527707983925666,0.6285393610547089,0.6916610887771518,0.7453559924999298,0.7915448249319448,0.8314794192830981,0.8660254037844386,0.8958064164776166,0.9212846639876111,0.9428090415820634,0.9606453592105879,0.9749960430435691,0.9860132971832694,0.9938079899999065,0.9984555975339683,1],
|
||||
inOut_circle: [0,0.003096005000046753,0.012501978478215436,0.028595479208968322,0.052096791761191696,0.08426029035845095,0.12732200375003505,0.18573031947264557,0.2709385763545744,0.5,0.7290614236454256,0.8142696805273546,0.8726779962499649,0.915739709641549,0.9479032082388084,0.9714045207910317,0.9874980215217846,0.9969039949999532,1],
|
||||
in_back_: [0,-0.004788556241426612,-0.017301289437585736,-0.0347587962962963,-0.05438167352537723,-0.07339051783264748,-0.08900592592592595,-0.09844849451303156,-0.0989388203017833,-0.08769750000000004,-0.06194513031550073,-0.018902307956104283,0.044210370370370254,0.13017230795610413,0.2417629080932785,0.3817615740740742,0.5529477091906719,0.7581007167352535,0.9999999999999998],
|
||||
out_back_: [2.220446049250313e-16,0.24189928326474652,0.44705229080932807,0.6182384259259258,0.7582370919067215,0.8698276920438959,0.9557896296296297,1.0189023079561044,1.0619451303155008,1.0876975,1.0989388203017834,1.0984484945130315,1.089005925925926,1.0733905178326475,1.0543816735253773,1.0347587962962963,1.0173012894375857,1.0047885562414267,1],
|
||||
};
|
||||
|
||||
Object.keys(Samples).forEach(function(type) {
|
||||
it('should ease ' + type, function() {
|
||||
var [modeName, easingName, isFunction] = type.split('_');
|
||||
var easing = Easing[easingName];
|
||||
if (isFunction !== undefined) {
|
||||
easing = easing();
|
||||
}
|
||||
var computed = sampleEasingFunction(Easing[modeName](easing));
|
||||
var samples = Samples[type];
|
||||
|
||||
computed.forEach((value, key) => {
|
||||
expect(value).toBeCloseTo(samples[key], 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,256 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest
|
||||
.dontMock('Interpolation')
|
||||
.dontMock('Easing');
|
||||
|
||||
var Interpolation = require('Interpolation');
|
||||
var Easing = require('Easing');
|
||||
|
||||
describe('Interpolation', () => {
|
||||
it('should work with defaults', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe(0);
|
||||
expect(interpolation(0.5)).toBe(0.5);
|
||||
expect(interpolation(0.8)).toBe(0.8);
|
||||
expect(interpolation(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with output range', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [100, 200],
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe(100);
|
||||
expect(interpolation(0.5)).toBe(150);
|
||||
expect(interpolation(0.8)).toBe(180);
|
||||
expect(interpolation(1)).toBe(200);
|
||||
});
|
||||
|
||||
it('should work with input range', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [100, 200],
|
||||
outputRange: [0, 1],
|
||||
});
|
||||
|
||||
expect(interpolation(100)).toBe(0);
|
||||
expect(interpolation(150)).toBe(0.5);
|
||||
expect(interpolation(180)).toBe(0.8);
|
||||
expect(interpolation(200)).toBe(1);
|
||||
});
|
||||
|
||||
it('should throw for non monotonic input ranges', () => {
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [0, 2, 1],
|
||||
outputRange: [0, 1, 2],
|
||||
})).toThrow();
|
||||
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [0, 1, 2],
|
||||
outputRange: [0, 3, 1],
|
||||
})).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with empty input range', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 10, 10],
|
||||
outputRange: [1, 2, 3],
|
||||
extrapolate: 'extend',
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe(1);
|
||||
expect(interpolation(5)).toBe(1.5);
|
||||
expect(interpolation(10)).toBe(2);
|
||||
expect(interpolation(10.1)).toBe(3);
|
||||
expect(interpolation(15)).toBe(3);
|
||||
});
|
||||
|
||||
it('should work with empty output range', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [1, 2, 3],
|
||||
outputRange: [0, 10, 10],
|
||||
extrapolate: 'extend',
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe(-10);
|
||||
expect(interpolation(1.5)).toBe(5);
|
||||
expect(interpolation(2)).toBe(10);
|
||||
expect(interpolation(2.5)).toBe(10);
|
||||
expect(interpolation(3)).toBe(10);
|
||||
expect(interpolation(4)).toBe(10);
|
||||
});
|
||||
|
||||
it('should work with easing', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
easing: Easing.quad,
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe(0);
|
||||
expect(interpolation(0.5)).toBe(0.25);
|
||||
expect(interpolation(0.9)).toBe(0.81);
|
||||
expect(interpolation(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('should work with extrapolate', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
extrapolate: 'extend',
|
||||
easing: Easing.quad,
|
||||
});
|
||||
|
||||
expect(interpolation(-2)).toBe(4);
|
||||
expect(interpolation(2)).toBe(4);
|
||||
|
||||
interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
extrapolate: 'clamp',
|
||||
easing: Easing.quad,
|
||||
});
|
||||
|
||||
expect(interpolation(-2)).toBe(0);
|
||||
expect(interpolation(2)).toBe(1);
|
||||
|
||||
interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
extrapolate: 'identity',
|
||||
easing: Easing.quad,
|
||||
});
|
||||
|
||||
expect(interpolation(-2)).toBe(-2);
|
||||
expect(interpolation(2)).toBe(2);
|
||||
});
|
||||
|
||||
it('should work with keyframes with extrapolate', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 10, 100, 1000],
|
||||
outputRange: [0, 5, 50, 500],
|
||||
extrapolate: true,
|
||||
});
|
||||
|
||||
expect(interpolation(-5)).toBe(-2.5);
|
||||
expect(interpolation(0)).toBe(0);
|
||||
expect(interpolation(5)).toBe(2.5);
|
||||
expect(interpolation(10)).toBe(5);
|
||||
expect(interpolation(50)).toBe(25);
|
||||
expect(interpolation(100)).toBe(50);
|
||||
expect(interpolation(500)).toBe(250);
|
||||
expect(interpolation(1000)).toBe(500);
|
||||
expect(interpolation(2000)).toBe(1000);
|
||||
});
|
||||
|
||||
it('should work with keyframes without extrapolate', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1, 2],
|
||||
outputRange: [0.2, 1, 0.2],
|
||||
extrapolate: 'clamp',
|
||||
});
|
||||
|
||||
expect(interpolation(5)).toBeCloseTo(0.2);
|
||||
});
|
||||
|
||||
it('should throw for an infinite input range', () => {
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [-Infinity, Infinity],
|
||||
outputRange: [0, 1],
|
||||
})).toThrow();
|
||||
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [-Infinity, 0, Infinity],
|
||||
outputRange: [1, 2, 3],
|
||||
})).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with negative infinite', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [-Infinity, 0],
|
||||
outputRange: [-Infinity, 0],
|
||||
easing: Easing.quad,
|
||||
extrapolate: 'identity',
|
||||
});
|
||||
|
||||
expect(interpolation(-Infinity)).toBe(-Infinity);
|
||||
expect(interpolation(-100)).toBeCloseTo(-10000);
|
||||
expect(interpolation(-10)).toBeCloseTo(-100);
|
||||
expect(interpolation(0)).toBeCloseTo(0);
|
||||
expect(interpolation(1)).toBeCloseTo(1);
|
||||
expect(interpolation(100)).toBeCloseTo(100);
|
||||
});
|
||||
|
||||
it('should work with positive infinite', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [5, Infinity],
|
||||
outputRange: [5, Infinity],
|
||||
easing: Easing.quad,
|
||||
extrapolate: 'identity',
|
||||
});
|
||||
|
||||
expect(interpolation(-100)).toBeCloseTo(-100);
|
||||
expect(interpolation(-10)).toBeCloseTo(-10);
|
||||
expect(interpolation(0)).toBeCloseTo(0);
|
||||
expect(interpolation(5)).toBeCloseTo(5);
|
||||
expect(interpolation(6)).toBeCloseTo(5 + 1);
|
||||
expect(interpolation(10)).toBeCloseTo(5 + 25);
|
||||
expect(interpolation(100)).toBeCloseTo(5 + (95 * 95));
|
||||
expect(interpolation(Infinity)).toBe(Infinity);
|
||||
});
|
||||
|
||||
it('should work with output ranges as string', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['rgba(0, 100, 200, 0)', 'rgba(50, 150, 250, 0.5)'],
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe('rgba(0, 100, 200, 0)');
|
||||
expect(interpolation(0.5)).toBe('rgba(25, 125, 225, 0.25)');
|
||||
expect(interpolation(1)).toBe('rgba(50, 150, 250, 0.5)');
|
||||
});
|
||||
|
||||
it('should work with negative and decimal values in string ranges', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['-100.5deg', '100deg'],
|
||||
});
|
||||
|
||||
expect(interpolation(0)).toBe('-100.5deg');
|
||||
expect(interpolation(0.5)).toBe('-0.25deg');
|
||||
expect(interpolation(1)).toBe('100deg');
|
||||
});
|
||||
|
||||
it('should crash when chaining an interpolation that returns a string', () => {
|
||||
var interpolation = Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
});
|
||||
expect(() => { interpolation('45rad'); }).toThrow();
|
||||
});
|
||||
|
||||
it('should crash when defining output range with different pattern', () => {
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['rgba(0, 100, 200, 0)', 'rgb(50, 150, 250)'],
|
||||
})).toThrow();
|
||||
|
||||
expect(() => Interpolation.create({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['20deg', '30rad'],
|
||||
})).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "react-animated",
|
||||
"description": "Animated provides powerful mechanisms for animating your React views",
|
||||
"version": "0.1.0",
|
||||
"keywords": [
|
||||
"react",
|
||||
"animated",
|
||||
"animation"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"main": "Animated.js",
|
||||
"readmeFilename": "README.md"
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule LayoutAnimation
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var keyMirror = require('keyMirror');
|
||||
|
||||
var TypesEnum = {
|
||||
spring: true,
|
||||
linear: true,
|
||||
easeInEaseOut: true,
|
||||
easeIn: true,
|
||||
easeOut: true,
|
||||
keyboard: true,
|
||||
};
|
||||
var Types = keyMirror(TypesEnum);
|
||||
|
||||
var PropertiesEnum = {
|
||||
opacity: true,
|
||||
scaleXY: true,
|
||||
};
|
||||
var Properties = keyMirror(PropertiesEnum);
|
||||
|
||||
var animChecker = createStrictShapeTypeChecker({
|
||||
duration: PropTypes.number,
|
||||
delay: PropTypes.number,
|
||||
springDamping: PropTypes.number,
|
||||
initialVelocity: PropTypes.number,
|
||||
type: PropTypes.oneOf(
|
||||
Object.keys(Types)
|
||||
),
|
||||
property: PropTypes.oneOf( // Only applies to create/delete
|
||||
Object.keys(Properties)
|
||||
),
|
||||
});
|
||||
|
||||
type Anim = {
|
||||
duration?: number;
|
||||
delay?: number;
|
||||
springDamping?: number;
|
||||
initialVelocity?: number;
|
||||
type?: $Enum<typeof TypesEnum>;
|
||||
property?: $Enum<typeof PropertiesEnum>;
|
||||
}
|
||||
|
||||
var configChecker = createStrictShapeTypeChecker({
|
||||
duration: PropTypes.number.isRequired,
|
||||
create: animChecker,
|
||||
update: animChecker,
|
||||
delete: animChecker,
|
||||
});
|
||||
|
||||
type Config = {
|
||||
duration: number;
|
||||
create?: Anim;
|
||||
update?: Anim;
|
||||
delete?: Anim;
|
||||
}
|
||||
|
||||
function configureNext(config: Config, onAnimationDidEnd?: Function) {
|
||||
configChecker({config}, 'config', 'LayoutAnimation.configureNext');
|
||||
RCTUIManager.configureNextLayoutAnimation(
|
||||
config, onAnimationDidEnd || function() {}, function() { /* unused */ }
|
||||
);
|
||||
}
|
||||
|
||||
function create(duration: number, type, creationProp): Config {
|
||||
return {
|
||||
duration,
|
||||
create: {
|
||||
type,
|
||||
property: creationProp,
|
||||
},
|
||||
update: {
|
||||
type,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var Presets = {
|
||||
easeInEaseOut: create(
|
||||
300, Types.easeInEaseOut, Properties.opacity
|
||||
),
|
||||
linear: create(
|
||||
500, Types.linear, Properties.opacity
|
||||
),
|
||||
spring: {
|
||||
duration: 700,
|
||||
create: {
|
||||
type: Types.linear,
|
||||
property: Properties.opacity,
|
||||
},
|
||||
update: {
|
||||
type: Types.spring,
|
||||
springDamping: 0.4,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Automatically animates views to their new positions when the
|
||||
* next layout happens.
|
||||
*
|
||||
* A common way to use this API is to call `LayoutAnimation.configureNext`
|
||||
* before calling `setState`.
|
||||
*/
|
||||
var LayoutAnimation = {
|
||||
/**
|
||||
* Schedules an animation to happen on the next layout.
|
||||
*
|
||||
* @param config Specifies animation properties:
|
||||
*
|
||||
* - `duration` in milliseconds
|
||||
* - `create`, config for animating in new views (see `Anim` type)
|
||||
* - `update`, config for animating views that have been updated
|
||||
* (see `Anim` type)
|
||||
*
|
||||
* @param onAnimationDidEnd Called when the animation finished.
|
||||
* Only supported on iOS.
|
||||
* @param onError Called on error. Only supported on iOS.
|
||||
*/
|
||||
configureNext,
|
||||
/**
|
||||
* Helper for creating a config for `configureNext`.
|
||||
*/
|
||||
create,
|
||||
Types,
|
||||
Properties,
|
||||
configChecker: configChecker,
|
||||
Presets,
|
||||
easeInEaseOut: configureNext.bind(
|
||||
null, Presets.easeInEaseOut
|
||||
),
|
||||
linear: configureNext.bind(
|
||||
null, Presets.linear
|
||||
),
|
||||
spring: configureNext.bind(
|
||||
null, Presets.spring
|
||||
),
|
||||
};
|
||||
|
||||
module.exports = LayoutAnimation;
|
||||
@@ -1,268 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule POPAnimationMixin
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var POPAnimationOrNull = require('POPAnimation');
|
||||
var React = require('React');
|
||||
|
||||
if (!POPAnimationOrNull) {
|
||||
// POP animation isn't available in the OSS fork - this is a temporary
|
||||
// workaround to enable its availability to be determined at runtime.
|
||||
module.exports = (null : ?{});
|
||||
} else {
|
||||
|
||||
// At this point, POPAnimationOrNull is guaranteed to be
|
||||
// non-null. Bring it local to preserve type refinement.
|
||||
var POPAnimation = POPAnimationOrNull;
|
||||
|
||||
var invariant = require('invariant');
|
||||
var warning = require('warning');
|
||||
|
||||
var POPAnimationMixin = {
|
||||
/**
|
||||
* Different ways to interpolate between beginning and end states
|
||||
* of properties during animation, such as spring, linear, and decay.
|
||||
*/
|
||||
AnimationTypes: POPAnimation.Types,
|
||||
AnimationProperties: POPAnimation.Properties,
|
||||
|
||||
getInitialState: function(): Object {
|
||||
this._popAnimationEnqueuedAnimationTimeouts = [];
|
||||
return {
|
||||
_currentAnimationsByNodeHandle: {},
|
||||
};
|
||||
},
|
||||
|
||||
_ensureBookkeepingSetup: function(nodeHandle: any) {
|
||||
if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) {
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = [];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Start animating the View with ref `refKey`.
|
||||
*
|
||||
* @param {key} refKey The key to reference the View to be animated.
|
||||
*
|
||||
* @param {number|Object} anim Either the identifier returned by
|
||||
* POPAnimation.create* or an object defining all the necessary
|
||||
* properties of the animation you wish to start (including type, matching
|
||||
* an entry in AnimationTypes).
|
||||
*
|
||||
* @param {func} doneCallback A callback fired when the animation is done, and
|
||||
* is passed a `finished` param that indicates whether the animation
|
||||
* completely finished, or was interrupted.
|
||||
*/
|
||||
startAnimation: function(
|
||||
refKey: string,
|
||||
anim: number | {type: number; property: number;},
|
||||
doneCallback: (finished: bool) => void
|
||||
) {
|
||||
var animID: number = 0;
|
||||
if (typeof anim === 'number') {
|
||||
animID = anim;
|
||||
} else {
|
||||
invariant(
|
||||
anim instanceof Object &&
|
||||
anim.type !== undefined &&
|
||||
anim.property !== undefined,
|
||||
'Animation definitions must specify a type of animation and a ' +
|
||||
'property to animate.'
|
||||
);
|
||||
animID = POPAnimation.createAnimation(anim.type, anim);
|
||||
}
|
||||
invariant(
|
||||
this.refs[refKey],
|
||||
'Invalid refKey ' + refKey + ' for anim:\n' + JSON.stringify(anim) +
|
||||
'\nvalid refs: ' + JSON.stringify(Object.keys(this.refs))
|
||||
);
|
||||
var refNodeHandle = React.findNodeHandle(this.refs[refKey]);
|
||||
this.startAnimationWithNodeHandle(refNodeHandle, animID, doneCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts an animation on a native node.
|
||||
*
|
||||
* @param {NodeHandle} nodeHandle Handle to underlying native node.
|
||||
* @see `startAnimation`.
|
||||
*/
|
||||
startAnimationWithNodeHandle: function(
|
||||
nodeHandle: any,
|
||||
animID: number,
|
||||
doneCallback: (finished: bool) => void
|
||||
) {
|
||||
this._ensureBookkeepingSetup(nodeHandle);
|
||||
var animations = this.state._currentAnimationsByNodeHandle[nodeHandle];
|
||||
var animIndex = animations.length;
|
||||
animations.push(animID);
|
||||
var cleanupWrapper = (finished) => {
|
||||
if (!this.isMounted()) {
|
||||
return;
|
||||
}
|
||||
animations[animIndex] = 0; // zero it out so we don't try to stop it
|
||||
var allDone = true;
|
||||
for (var ii = 0; ii < animations.length; ii++) {
|
||||
if (animations[ii]) {
|
||||
allDone = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allDone) {
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined;
|
||||
}
|
||||
doneCallback && doneCallback(finished);
|
||||
};
|
||||
// Hack to aviod race condition in POP:
|
||||
var animationTimeoutHandler = setTimeout(() => {
|
||||
POPAnimation.addAnimation(nodeHandle, animID, cleanupWrapper);
|
||||
}, 1);
|
||||
this._popAnimationEnqueuedAnimationTimeouts.push(animationTimeoutHandler);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts multiple animations with one shared callback that is called when all
|
||||
* animations complete.
|
||||
*
|
||||
* @param {Array(Object} animations Array of objects defining all the
|
||||
* animations to start, each with shape `{ref|nodeHandle, anim}`.
|
||||
* @param {func} onSuccess A callback fired when all animations have returned,
|
||||
* and is passed a finished arg that is true if all animations finished
|
||||
* completely.
|
||||
* @param {func} onFailure Not supported yet.
|
||||
*/
|
||||
startAnimations: function(
|
||||
animations: Array<Object>,
|
||||
onSuccess: (finished: boolean) => void,
|
||||
onFailure: () => void
|
||||
) {
|
||||
var numReturned = 0;
|
||||
var numFinished = 0;
|
||||
var numAnimations = animations.length;
|
||||
var metaCallback = (finished) => {
|
||||
if (finished) {
|
||||
++numFinished;
|
||||
}
|
||||
if (++numReturned === numAnimations) {
|
||||
onSuccess && onSuccess(numFinished === numAnimations);
|
||||
}
|
||||
};
|
||||
animations.forEach((anim) => {
|
||||
warning(
|
||||
anim.ref != null || anim.nodeHandle != null &&
|
||||
!anim.ref !== !anim.nodeHandle,
|
||||
'Animations must be specified with either ref xor nodeHandle'
|
||||
);
|
||||
if (anim.ref) {
|
||||
this.startAnimation(anim.ref, anim.anim, metaCallback);
|
||||
} else if (anim.nodeHandle) {
|
||||
this.startAnimationWithNodeHandle(anim.nodeHandle, anim.anim, metaCallback);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations operating on the View with native node handle
|
||||
* `nodeHandle`.
|
||||
*
|
||||
* @param {NodeHandle} component The instance to stop animations
|
||||
* on. Do not pass a composite component.
|
||||
*/
|
||||
stopNodeHandleAnimations: function(nodeHandle: any) {
|
||||
if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) {
|
||||
return;
|
||||
}
|
||||
var anims = this.state._currentAnimationsByNodeHandle[nodeHandle];
|
||||
for (var i = 0; i < anims.length; i++) {
|
||||
var anim = anims[i];
|
||||
if (anim) {
|
||||
// Note: Converting the string key to a number `nodeHandle`.
|
||||
POPAnimation.removeAnimation(+nodeHandle, anim);
|
||||
}
|
||||
}
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations operating on the View with ref `refKey`.
|
||||
*
|
||||
* @param {key} refKey The key to reference the View to be animated.
|
||||
*/
|
||||
stopAnimations: function(refKey: string) {
|
||||
invariant(this.refs[refKey], 'invalid ref');
|
||||
this.stopNodeHandleAnimations(React.findNodeHandle(this.refs[refKey]));
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations created by this component on itself and
|
||||
* subviews.
|
||||
*/
|
||||
stopAllAnimations: function() {
|
||||
for (var nodeHandle in this.state._currentAnimationsByNodeHandle) {
|
||||
this.stopNodeHandleAnimations(nodeHandle);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Animates size and position of a view referenced by `refKey` to a specific
|
||||
* frame.
|
||||
*
|
||||
* @param {key} refKey ref key for view to animate.
|
||||
* @param {Object} frame The frame to animate the view to, specified as {left,
|
||||
* top, width, height}.
|
||||
* @param {const} type What type of interpolation to use, selected from
|
||||
* `inperpolationTypes`.
|
||||
* @param {Object} event Event encapsulating synthetic and native data that
|
||||
* may have triggered this animation. Velocity is extracted from it if
|
||||
* possible and applied to the animation.
|
||||
* @param {func} doneCallback A callback fired when the animation is done, and
|
||||
* is passed a `finished` param that indicates whether the animation
|
||||
* completely finished, or was interrupted.
|
||||
*/
|
||||
animateToFrame: function(
|
||||
refKey: string,
|
||||
frame: {left: number; top: number; width: number; height: number;},
|
||||
type: number,
|
||||
velocity: number,
|
||||
doneCallback: (finished: boolean) => void
|
||||
) {
|
||||
var animFrame = { // Animations use a centered coordinate system.
|
||||
x: frame.left + frame.width / 2,
|
||||
y: frame.top + frame.height / 2,
|
||||
w: frame.width,
|
||||
h: frame.height
|
||||
};
|
||||
var posAnim = POPAnimation.createAnimation(type, {
|
||||
property: POPAnimation.Properties.position,
|
||||
toValue: [animFrame.x, animFrame.y],
|
||||
velocity: velocity || [0, 0],
|
||||
});
|
||||
var sizeAnim = POPAnimation.createAnimation(type, {
|
||||
property: POPAnimation.Properties.size,
|
||||
toValue: [animFrame.w, animFrame.h]
|
||||
});
|
||||
this.startAnimation(refKey, posAnim, doneCallback);
|
||||
this.startAnimation(refKey, sizeAnim);
|
||||
},
|
||||
|
||||
// Cleanup any potentially leaked animations.
|
||||
componentWillUnmount: function() {
|
||||
this.stopAllAnimations();
|
||||
this._popAnimationEnqueuedAnimationTimeouts.forEach(animationTimeoutHandler => {
|
||||
clearTimeout(animationTimeoutHandler);
|
||||
});
|
||||
this._popAnimationEnqueuedAnimationTimeouts = [];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = POPAnimationMixin;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user