[RN] Document Animated.js
This commit is contained in:
parent
54f91bd951
commit
cc1a9fa3f3
|
@ -503,6 +503,12 @@ type ValueListenerCallback = (state: {value: number}) => void;
|
||||||
|
|
||||||
var _uniqueId = 1;
|
var _uniqueId = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard value for driving animations. One `Animated.Value` can drive
|
||||||
|
* multiple properties in a synchronized fashion, but can only be driven by one
|
||||||
|
* mechanism at a time. Using a new mechanism (e.g. starting a new animation,
|
||||||
|
* or calling `setValue`) will stop any previous ones.
|
||||||
|
*/
|
||||||
class AnimatedValue extends AnimatedWithChildren {
|
class AnimatedValue extends AnimatedWithChildren {
|
||||||
_value: number;
|
_value: number;
|
||||||
_offset: number;
|
_offset: number;
|
||||||
|
@ -526,6 +532,10 @@ class AnimatedValue extends AnimatedWithChildren {
|
||||||
return this._value + this._offset;
|
return this._value + this._offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directly set the value. This will stop any animations running on the value
|
||||||
|
* and udpate all the bound properties.
|
||||||
|
*/
|
||||||
setValue(value: number): void {
|
setValue(value: number): void {
|
||||||
if (this._animation) {
|
if (this._animation) {
|
||||||
this._animation.stop();
|
this._animation.stop();
|
||||||
|
@ -534,15 +544,29 @@ class AnimatedValue extends AnimatedWithChildren {
|
||||||
this._updateValue(value);
|
this._updateValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an offset that is applied on top of whatever value is set, whether via
|
||||||
|
* `setValue`, an animation, or `Animated.event`. Useful for compensating
|
||||||
|
* things like the start of a pan gesture.
|
||||||
|
*/
|
||||||
setOffset(offset: number): void {
|
setOffset(offset: number): void {
|
||||||
this._offset = offset;
|
this._offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges the offset value into the base value and resets the offset to zero.
|
||||||
|
* The final output of the value is unchanged.
|
||||||
|
*/
|
||||||
flattenOffset(): void {
|
flattenOffset(): void {
|
||||||
this._value += this._offset;
|
this._value += this._offset;
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an asynchronous listener to the value so you can observe updates from
|
||||||
|
* animations or whathaveyou. This is useful because there is no way to
|
||||||
|
* syncronously read the value because it might be driven natively.
|
||||||
|
*/
|
||||||
addListener(callback: ValueListenerCallback): string {
|
addListener(callback: ValueListenerCallback): string {
|
||||||
var id = String(_uniqueId++);
|
var id = String(_uniqueId++);
|
||||||
this._listeners[id] = callback;
|
this._listeners[id] = callback;
|
||||||
|
@ -557,6 +581,30 @@ class AnimatedValue extends AnimatedWithChildren {
|
||||||
this._listeners = {};
|
this._listeners = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops any running animation or tracking. `callback` is invoked with the
|
||||||
|
* final value after stopping the animation, which is useful for updating
|
||||||
|
* state to match the animation position with layout.
|
||||||
|
*/
|
||||||
|
stopAnimation(callback?: ?(value: number) => void): void {
|
||||||
|
this.stopTracking();
|
||||||
|
this._animation && this._animation.stop();
|
||||||
|
this._animation = null;
|
||||||
|
callback && callback(this.__getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolates the value before updating the property, e.g. mapping 0-1 to
|
||||||
|
* 0-10.
|
||||||
|
*/
|
||||||
|
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
||||||
|
return new AnimatedInterpolation(this, Interpolation.create(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typically only used internally, but could be used by a custom Animation
|
||||||
|
* class.
|
||||||
|
*/
|
||||||
animate(animation: Animation, callback: ?EndCallback): void {
|
animate(animation: Animation, callback: ?EndCallback): void {
|
||||||
var handle = InteractionManager.createInteractionHandle();
|
var handle = InteractionManager.createInteractionHandle();
|
||||||
var previousAnimation = this._animation;
|
var previousAnimation = this._animation;
|
||||||
|
@ -576,27 +624,22 @@ class AnimatedValue extends AnimatedWithChildren {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopAnimation(callback?: ?(value: number) => void): void {
|
/**
|
||||||
this.stopTracking();
|
* Typically only used internally.
|
||||||
this._animation && this._animation.stop();
|
*/
|
||||||
this._animation = null;
|
|
||||||
callback && callback(this.__getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
stopTracking(): void {
|
stopTracking(): void {
|
||||||
this._tracking && this._tracking.__detach();
|
this._tracking && this._tracking.__detach();
|
||||||
this._tracking = null;
|
this._tracking = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typically only used internally.
|
||||||
|
*/
|
||||||
track(tracking: Animated): void {
|
track(tracking: Animated): void {
|
||||||
this.stopTracking();
|
this.stopTracking();
|
||||||
this._tracking = tracking;
|
this._tracking = tracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolate(config: InterpolationConfigType): AnimatedInterpolation {
|
|
||||||
return new AnimatedInterpolation(this, Interpolation.create(config));
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateValue(value: number): void {
|
_updateValue(value: number): void {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
_flush(this);
|
_flush(this);
|
||||||
|
@ -607,6 +650,45 @@ class AnimatedValue extends AnimatedWithChildren {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValueXYListenerCallback = (value: {x: number; y: number}) => void;
|
type ValueXYListenerCallback = (value: {x: number; y: number}) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2D Value for driving 2D animations, such as pan gestures. Almost identical
|
||||||
|
* API to normal `Animated.Value`, but multiplexed. Contains two regular
|
||||||
|
* `Animated.Value`s under the hood. Example:
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* class DraggableView extends React.Component {
|
||||||
|
* constructor(props) {
|
||||||
|
* super(props);
|
||||||
|
* this.state = {
|
||||||
|
* pan: new Animated.ValueXY(), // inits to zero
|
||||||
|
* };
|
||||||
|
* this.state.panResponder = PanResponder.create({
|
||||||
|
* onStartShouldSetPanResponder: () => true,
|
||||||
|
* onPanResponderMove: Animated.event([null, {
|
||||||
|
* dx: this.state.pan.x, // x,y are Animated.Value
|
||||||
|
* dy: this.state.pan.y,
|
||||||
|
* }]),
|
||||||
|
* onPanResponderRelease: () => {
|
||||||
|
* Animated.spring(
|
||||||
|
* this.state.pan, // Auto-multiplexed
|
||||||
|
* {toValue: {x: 0, y: 0}} // Back to zero
|
||||||
|
* ).start();
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* render() {
|
||||||
|
* return (
|
||||||
|
* <Animated.View
|
||||||
|
* {...this.state.panResponder.panHandlers}
|
||||||
|
* style={this.state.pan.getLayout()}>
|
||||||
|
* {this.props.children}
|
||||||
|
* </Animated.View>
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*```
|
||||||
|
*/
|
||||||
class AnimatedValueXY extends AnimatedWithChildren {
|
class AnimatedValueXY extends AnimatedWithChildren {
|
||||||
x: AnimatedValue;
|
x: AnimatedValue;
|
||||||
y: AnimatedValue;
|
y: AnimatedValue;
|
||||||
|
@ -677,6 +759,13 @@ class AnimatedValueXY extends AnimatedWithChildren {
|
||||||
delete this._listeners[id];
|
delete this._listeners[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts `{x, y}` into `{left, top}` for use in style, e.g.
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* style={this.state.anim.getLayout()}
|
||||||
|
*```
|
||||||
|
*/
|
||||||
getLayout(): {[key: string]: AnimatedValue} {
|
getLayout(): {[key: string]: AnimatedValue} {
|
||||||
return {
|
return {
|
||||||
left: this.x,
|
left: this.x,
|
||||||
|
@ -684,6 +773,15 @@ class AnimatedValueXY extends AnimatedWithChildren {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts `{x, y}` into a useable translation transform, e.g.
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* style={{
|
||||||
|
* transform: this.state.anim.getTranslateTransform()
|
||||||
|
* }}
|
||||||
|
*```
|
||||||
|
*/
|
||||||
getTranslateTransform(): Array<{[key: string]: AnimatedValue}> {
|
getTranslateTransform(): Array<{[key: string]: AnimatedValue}> {
|
||||||
return [
|
return [
|
||||||
{translateX: this.x},
|
{translateX: this.x},
|
||||||
|
@ -1235,21 +1333,6 @@ var stagger = function(
|
||||||
|
|
||||||
type Mapping = {[key: string]: Mapping} | AnimatedValue;
|
type Mapping = {[key: string]: Mapping} | AnimatedValue;
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an array of mappings and extracts values from each arg accordingly,
|
|
||||||
* then calls setValue on the mapped outputs. e.g.
|
|
||||||
*
|
|
||||||
* onScroll={this.AnimatedEvent(
|
|
||||||
* [{nativeEvent: {contentOffset: {x: this._scrollX}}}]
|
|
||||||
* {listener} // optional listener invoked asynchronously
|
|
||||||
* )
|
|
||||||
* ...
|
|
||||||
* onPanResponderMove: this.AnimatedEvent([
|
|
||||||
* null, // raw event arg
|
|
||||||
* {dx: this._panX}, // gestureState arg
|
|
||||||
* ]),
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
type EventConfig = {listener?: ?Function};
|
type EventConfig = {listener?: ?Function};
|
||||||
var event = function(
|
var event = function(
|
||||||
argMapping: Array<?Mapping>,
|
argMapping: Array<?Mapping>,
|
||||||
|
@ -1287,23 +1370,179 @@ var event = function(
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animations are an important part of modern UX, and the `Animated`
|
||||||
|
* library is designed to make them fluid, powerful, and easy to build and
|
||||||
|
* maintain.
|
||||||
|
*
|
||||||
|
* The simplest workflow is to create an `Animated.Value`, hook it up to one or
|
||||||
|
* more style attributes of an animated component, and then drive updates either
|
||||||
|
* via animations, such as `Animated.timing`, or by hooking into gestures like
|
||||||
|
* panning or scolling via `Animated.event`. `Animated.Value` can also bind to
|
||||||
|
* props other than style, and can be interpolated as well. Here is a basic
|
||||||
|
* example of a container view that will fade in when it's mounted:
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* class FadeInView extends React.Component {
|
||||||
|
* constructor(props) {
|
||||||
|
* super(props);
|
||||||
|
* this.state = {
|
||||||
|
* fadeAnim: new Animated.Value(0), // init opacity 0
|
||||||
|
* };
|
||||||
|
* }
|
||||||
|
* componentDidMount() {
|
||||||
|
* Animated.timing( // Uses easing functions
|
||||||
|
* this.state.fadeAnim, // The value to drive
|
||||||
|
* {toValue: 1}, // Configuration
|
||||||
|
* ).start(); // Don't forget start!
|
||||||
|
* }
|
||||||
|
* render() {
|
||||||
|
* return (
|
||||||
|
* <Animated.View // Special animatable View
|
||||||
|
* style={{opacity: this.state.fadeAnim}}> // Binds
|
||||||
|
* {this.props.children}
|
||||||
|
* </Animated.View>
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*```
|
||||||
|
*
|
||||||
|
* Note that only animatable components can be animated. `View`, `Text`, and
|
||||||
|
* `Image` are already provided, and you can create custom ones with
|
||||||
|
* `createAnimatedComponent`. These special components do the magic of binding
|
||||||
|
* the animated values to the properties, and do targetted native updates to
|
||||||
|
* avoid the cost of the react render and reconciliation process on every frame.
|
||||||
|
* They also handle cleanup on unmount so they are safe by default.
|
||||||
|
*
|
||||||
|
* Animations are heavily configurable. Custom and pre-defined easing
|
||||||
|
* functions, delays, durations, decay factors, spring constants, and more can
|
||||||
|
* all be tweaked depending on the type of animation.
|
||||||
|
*
|
||||||
|
* A single `Animated.Value` can drive any number of properties, and each
|
||||||
|
* property can be run through an interpolation first. An interpolation maps
|
||||||
|
* input ranges to output ranges, typically using a linear interpolation but
|
||||||
|
* also supports easing functions. By default, it will extrapolate the curve
|
||||||
|
* beyond the ranges given, but you can also have it clamp the output value.
|
||||||
|
*
|
||||||
|
* For example, you may want to think about your `Animated.Value` as going from
|
||||||
|
* 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to
|
||||||
|
* 1. This can easily be done by modifying `style` in the example above like so:
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* style={{
|
||||||
|
* opacity: this.state.fadeAnim, // Binds directly
|
||||||
|
* transform: [{
|
||||||
|
* translateY: this.state.fadeAnim.interpolate({
|
||||||
|
* inputRange: [0, 1],
|
||||||
|
* outputRange: [150, 0] // 0 : 150, 0.5 : 75, 1 : 0
|
||||||
|
* }),
|
||||||
|
* }],
|
||||||
|
* }}>
|
||||||
|
*```
|
||||||
|
*
|
||||||
|
* Animations can also be combined in complex ways using composition functions
|
||||||
|
* such as `sequence` and `parallel`, and can also be chained together simply
|
||||||
|
* by setting the `toValue` of one animation to be another `Animated.Value`.
|
||||||
|
*
|
||||||
|
* `Animated.ValueXY` is handy for 2D animations, like panning, and there are
|
||||||
|
* other helpful additions like `setOffset` and `getLayout` to aid with typical
|
||||||
|
* interaction patterns, like drag-and-drop.
|
||||||
|
*
|
||||||
|
* You can see more example usage in `AnimationExample.js`, the Gratuitous
|
||||||
|
* Animation App, and [Animations documentation guide](http://facebook.github.io/react-native/docs/animations.html).
|
||||||
|
*
|
||||||
|
* Note that `Animated` is designed to be fully serializable so that animations
|
||||||
|
* can be run in a high performace way, independent of the normal JavaScript
|
||||||
|
* event loop. This does influence the API, so keep that in mind when it seems a
|
||||||
|
* little trickier to do something compared to a fully synchronous system.
|
||||||
|
* Checkout `Animated.Value.addListener` as a way to work around some of these
|
||||||
|
* limitations, but use it sparingly since it might have performance
|
||||||
|
* implications in the future.
|
||||||
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
delay,
|
/**
|
||||||
sequence,
|
* Standard value class for driving animations. Typically initialized with
|
||||||
parallel,
|
* `new Animated.Value(0);`
|
||||||
stagger,
|
*/
|
||||||
|
Value: AnimatedValue,
|
||||||
|
/**
|
||||||
|
* 2D value class for driving 2D animations, such as pan gestures.
|
||||||
|
*/
|
||||||
|
ValueXY: AnimatedValueXY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An animatable View component.
|
||||||
|
*/
|
||||||
|
View: createAnimatedComponent(View),
|
||||||
|
/**
|
||||||
|
* An animatable Text component.
|
||||||
|
*/
|
||||||
|
Text: createAnimatedComponent(Text),
|
||||||
|
/**
|
||||||
|
* An animatable Image component.
|
||||||
|
*/
|
||||||
|
Image: createAnimatedComponent(Image),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates a value from an initial velocity to zero based on a decay
|
||||||
|
* coefficient.
|
||||||
|
*/
|
||||||
decay,
|
decay,
|
||||||
|
/**
|
||||||
|
* Animates a value along a timed easing curve. The `Easing` module has tons
|
||||||
|
* of pre-defined curves, or you can use your own function.
|
||||||
|
*/
|
||||||
timing,
|
timing,
|
||||||
|
/**
|
||||||
|
* Spring animation based on Rebound and Origami. Tracks velocity state to
|
||||||
|
* create fluid motions as the `toValue` updates, and can be chained together.
|
||||||
|
*/
|
||||||
spring,
|
spring,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an animation after the given delay.
|
||||||
|
*/
|
||||||
|
delay,
|
||||||
|
/**
|
||||||
|
* Starts an array of animations in order, waiting for each to complete
|
||||||
|
* before starting the next. If the current running animation is stopped, no
|
||||||
|
* following animations will be started.
|
||||||
|
*/
|
||||||
|
sequence,
|
||||||
|
/**
|
||||||
|
* Starts an array of animations all at the same time. By default, if one
|
||||||
|
* of the animations is stopped, they will all be stopped. You can override
|
||||||
|
* this with the `stopTogether` flag.
|
||||||
|
*/
|
||||||
|
parallel,
|
||||||
|
/**
|
||||||
|
* Array of animations may run in parallel (overlap), but are started in
|
||||||
|
* sequence with successive delays. Nice for doing trailing effects.
|
||||||
|
*/
|
||||||
|
stagger,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes an array of mappings and extracts values from each arg accordingly,
|
||||||
|
* then calls `setValue` on the mapped outputs. e.g.
|
||||||
|
*
|
||||||
|
*```javascript
|
||||||
|
* onScroll={this.AnimatedEvent(
|
||||||
|
* [{nativeEvent: {contentOffset: {x: this._scrollX}}}]
|
||||||
|
* {listener}, // Optional async listener
|
||||||
|
* )
|
||||||
|
* ...
|
||||||
|
* onPanResponderMove: this.AnimatedEvent([
|
||||||
|
* null, // raw event arg ignored
|
||||||
|
* {dx: this._panX}, // gestureState arg
|
||||||
|
* ]),
|
||||||
|
*```
|
||||||
|
*/
|
||||||
event,
|
event,
|
||||||
|
|
||||||
Value: AnimatedValue,
|
/**
|
||||||
ValueXY: AnimatedValueXY,
|
* Make any React component Animatable. Used to create `Animated.View`, etc.
|
||||||
__PropsOnlyForTests: AnimatedProps,
|
*/
|
||||||
View: createAnimatedComponent(View),
|
|
||||||
Text: createAnimatedComponent(Text),
|
|
||||||
Image: createAnimatedComponent(Image),
|
|
||||||
createAnimatedComponent,
|
createAnimatedComponent,
|
||||||
|
|
||||||
|
__PropsOnlyForTests: AnimatedProps,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue