Skip to content

Commit

Permalink
Merge branch 'release/0.8.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
SoHotSoup committed Dec 2, 2016
2 parents 54c9abe + 8c1cbde commit 6fbac78
Show file tree
Hide file tree
Showing 17 changed files with 246 additions and 31 deletions.
5 changes: 5 additions & 0 deletions examples/ShoutemAnimation/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import Parallax from './Parallax';
import HeroHeader from './HeroHeader';
import FadeInOut from './FadeInOut';
import ZoomInOut from './ZoomInOut';
import ZoomInTouchable from './ZoomInTouchable';

const examples = {
Parallax,
HeroHeader,
FadeInOut,
ZoomInOut,
ZoomInTouchable,
};

export class App extends Component {
Expand Down Expand Up @@ -46,6 +48,9 @@ export class App extends Component {
}, {
example: 'ZoomIn + ZoomOut (TimerDriver)',
component: 'ZoomInOut',
}, {
example: 'ZoomIn (TouchableDriver)',
component: 'ZoomInTouchable',
}]}
onOptionSelected={(option) => this.setState({ selectedComponent: option.component })}
titleProperty="example"
Expand Down
38 changes: 38 additions & 0 deletions examples/ShoutemAnimation/ZoomInTouchable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { Component } from 'react';
import { ScrollView } from 'react-native';

import {
ZoomIn,
TouchableDriver,
} from '@shoutem/animation';


import {
Button,
Row,
Icon,
Text,
View,
} from '@shoutem/ui';

export default class ZoomInTouchableExample extends Component {
render() {
const driver = new TouchableDriver();

return (
<View>
<Row>
<View styleName="horizontal h-center">
<ZoomIn driver={driver} maxFactor={1.3}>
<Button {...driver.touchableViewProps}>
<Icon name="add-to-favorites-full" />
<Text>{"TOUCH ME, I'M ZOOMING IN"}</Text>
</Button>
</ZoomIn>
</View>
</Row>
</View>
);
}
}

29 changes: 18 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
export { default as makeZoomable } from './ZoomableComponent';
export { ScrollDriver } from './ScrollDriver';
export { TimingDriver } from './TimingDriver';
export { Parallax } from './Parallax';
export { FadeIn } from './FadeIn';
export { FadeOut } from './FadeOut';
export { ZoomIn } from './ZoomIn';
export { ZoomOut } from './ZoomOut';
export { HeroHeader } from './HeroHeader';
export { DriverShape } from './DriverShape';
export { connectAnimation } from './connectAnimation';
export { default as makeZoomable } from './src/components/ZoomableComponent';
export { ScrollDriver } from './src/drivers/ScrollDriver';
export { TimingDriver } from './src/drivers/TimingDriver';
export { TouchableDriver } from './src/drivers/TouchableDriver';
export { Parallax } from './src/animations/Parallax';
export { FadeIn } from './src/animations/FadeIn';
export { FadeOut } from './src/animations/FadeOut';
export { ZoomIn } from './src/animations/ZoomIn';
export { ZoomOut } from './src/animations/ZoomOut';
export { HeroHeader } from './src/animations/HeroHeader';
export { DriverShape } from './src/drivers/DriverShape';
export { connectAnimation } from './src/components/connectAnimation';
export {
isAnimatedStyleValue,
getAnimatedStyleValue,
addAnimatedValueListener,
removeAnimatedValueListener,
} from './src/utils/animated-style';
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shoutem/animation",
"version": "0.8.7",
"version": "0.8.9",
"description": "Shoutem Animation Library",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion FadeIn.js → src/animations/FadeIn.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Animated, View } from 'react-native';
import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';
/*
* FadeIn Component adds fade in effect to its children components.
* Connect it to an animation driver and pass the input range to animate it.
Expand Down
2 changes: 1 addition & 1 deletion FadeOut.js → src/animations/FadeOut.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Animated, View } from 'react-native';
import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';
/*
* FadeOut Component adds fade out effect to its children components.
* Connect it to driver and pass the input range to animate it.
Expand Down
2 changes: 1 addition & 1 deletion HeroHeader.js → src/animations/HeroHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { View } from 'react-native';
import { ZoomOut } from './ZoomOut';
import { Parallax } from './Parallax';
import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';
/*
* HeroHeader adds complex effect to its children components.
* Connect it to driver to animate it.
Expand Down
25 changes: 17 additions & 8 deletions Parallax.js → src/animations/Parallax.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { Component, } from 'react';
import NativeMethodsMixin from 'react/lib/NativeMethodsMixin';
import { Animated, View, Dimensions } from 'react-native';
import React, { Component } from 'react';
import ReactNative, { Animated, View, Dimensions, UIManager } from 'react-native';

import { DriverShape } from './DriverShape';
const findNodeHandle = ReactNative.findNodeHandle;

import { DriverShape } from '../drivers/DriverShape';
/*
* Parallax Component adds parallax effect to its children components.
* Connect it to driver to animate it. By default children will by
Expand Down Expand Up @@ -73,15 +74,18 @@ export class Parallax extends Component {
this.translation = new Animated.Value(0);
this.calculateTranslation = this.calculateTranslation.bind(this);
this.measure = this.measure.bind(this);
this.handleMeasure = this.handleMeasure.bind(this);
this.state = {
y: 0,
};
}

handleMeasure(x, y, width, height, pageX, pageY) {
this.setState({ x: pageX, y: pageY });
};

measure() {
NativeMethodsMixin.measure.call(this, (x, y, width, height, pageX, pageY) => {
this.setState({ x: pageX, y: pageY });
});
UIManager.measure(findNodeHandle(this), handleMeasure);
}

componentDidMount() {
Expand All @@ -97,7 +101,12 @@ export class Parallax extends Component {

componentWillMount() {
const { driver } = this.props;
driver.value.addListener(this.calculateTranslation);
this.animationListener = driver.value.addListener(this.calculateTranslation);
}

componentWillUnmount() {
const { driver } = this.props;
driver.value.removeListener(this.animationListener);
}

render() {
Expand Down
2 changes: 1 addition & 1 deletion ZoomIn.js → src/animations/ZoomIn.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Animated, View } from 'react-native';
import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';
/*
* ZoomIn Component adds zoom in effect to its children components.
* Connect it to driver and pass the input range to animate it.
Expand Down
2 changes: 1 addition & 1 deletion ZoomOut.js → src/animations/ZoomOut.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Animated, View } from 'react-native';
import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';
/*
* ZoomOut Component adds zoom out effect to its children components.
* Connect it to driver and pass the input range to animate it.
Expand Down
File renamed without changes.
22 changes: 16 additions & 6 deletions connectAnimation.js → src/components/connectAnimation.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Animated } from 'react-native';
import hoistStatics from 'hoist-non-react-statics';
import * as _ from 'lodash';

import { DriverShape } from './DriverShape';
import { DriverShape } from '../drivers/DriverShape';

const ANIMATION_SUFFIX = 'Animation';

Expand Down Expand Up @@ -65,6 +65,10 @@ function resolveAnimatedStyle({
return _.mergeWith(removeAnimationsFromStyle(style), animatedStyle, transferAnimatedValues);
}

const defaultOptions = {
createAnimatedComponent: true,
};

/**
* Higher order component that creates animated component which could be animated by
* list of passed animations. Animations are ran by driver, that could be send through
Expand All @@ -86,9 +90,15 @@ function resolveAnimatedStyle({
* in described animation component would fadeOut when scroll is equal its height
* @param WrappedComponent component you want to be Animated
* @param animations collection of available animations
* @param options additional connect options
* @param options.createAnimatedComponent determines if the connected component
* will be wrapped in an animated component, true by default. You may set this
* to false if your component already knows how to work with animated style values.
*/
export function connectAnimation(WrappedComponent, animations = {}) {
const AnimatedWrappedComponent = Animated.createAnimatedComponent(WrappedComponent);
export function connectAnimation(WrappedComponent, animations = {}, options = defaultOptions) {
const AnimatedWrappedComponent = options.createAnimatedComponent ?
Animated.createAnimatedComponent(WrappedComponent) :
WrappedComponent;

class AnimatedComponent extends Component {
static propTypes = {
Expand Down Expand Up @@ -121,15 +131,15 @@ export function connectAnimation(WrappedComponent, animations = {}) {
* and it should return style object
*/
animation: React.PropTypes.func,
}
};

static defaultProps = {
animationOptions: {},
}
};

static contextTypes = {
animationDriver: DriverShape,
}
};

constructor(props, context) {
super(props, context);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
62 changes: 62 additions & 0 deletions src/drivers/TouchableDriver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
Animated,
Easing,
} from 'react-native';

/**
* Returns the default animation callback to use.
*
* @param {Animated.Value} value
* @param {double} toValue
* @param {Object} animationOptions
* @returns {CompositeAnimation}
*/
function defaultAnimation(value, toValue, animationOptions) {
return Animated.timing(
value,
{
toValue: toValue,
...animationOptions
}
);
}

/**
* Animation driver that creates an animated value changed on press events.
*
* Assign onPressIn and onPressOut props of React Native Touchable*, and
* pass instance to any @shoutem/animation animation to run it
* e.g.:
* driver = new TouchableDriver();
* ...
* <TouchableOpacity {...driver.touchableViewProps}>
* ...
* <ZoomIn driver={driver}>
*/
export class TouchableDriver {

/**
* @param {Object} options Animation options.
*/
constructor(options) {
this.animationOptions = Object.assign({
easing: Easing.elastic(1),
duration: 150,
}, options);
this.value = new Animated.Value(0);
this.onPressIn = this.onPressIn.bind(this);
this.onPressOut = this.onPressOut.bind(this);
this.touchableViewProps = {
onPressIn: this.onPressIn,
onPressOut: this.onPressOut,
};
}

onPressIn() {
defaultAnimation(this.value, 1, this.animationOptions).start();
}

onPressOut() {
defaultAnimation(this.value, 0, this.animationOptions).start();
}
}
84 changes: 84 additions & 0 deletions src/utils/animated-style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Animated } from 'react-native';

/**
* Checks if a style value is animated.
*
* @param value The value to check.
* @returns {boolean} `true` if a value is animated, `false` otherwise.
*/
export const isAnimatedStyleValue = (value) => value && typeof value.interpolate === 'function';

/**
* Gets the current value of an animated style value. If
* a value isn't animated, the original value will be returned.
*
* @param value The style value.
* @return {*} The current value of a provided animated value.
*/
export const getAnimatedStyleValue = (value) => {
if (isAnimatedStyleValue(value)) {
// If this is an animated value, we want to convert it to
// a plain object in order to get its current value.
return value.toJSON();
}

return value;
};

/**
* Finds the closest `AnimatedValue` instance from the given
* animated style value (e.g., AnimatedInterpolation, etc.).
* This function will crawl the animated style hierarchy until
* it finds the first `AnimatedValue` instance.
*
* @param animatedStyleValue The starting animated style value.
* @returns {*} The closest `AnimatedValue`.
*/
const findAnimatedValue = (animatedStyleValue) => {
if (animatedStyleValue instanceof Animated.Value) {
return animatedStyleValue;
}

const parent = animatedStyleValue._parent;
if (parent) {
return findAnimatedValue(parent);
}

return undefined;
};

/**
* Adds a listener to the animated value, or the closest parent
* that is an animated value. This function is useful in components
* that receive animated interpolations but need to react to changes
* of those values during animations.
*
* @param styleValue The style value to add the listener to.
* @param listener The listener to add.
* @returns {string} The listener id, or `undefined` if the
* listener couldn't be registered.
*/
export const addAnimatedValueListener = (styleValue, listener) => {
const animatedValue = findAnimatedValue(styleValue);
if (animatedValue) {
return animatedValue.addListener(listener);
}

return undefined;
};

/**
* Remove the animated value listener with the given id. The
* listener will be removed from the `styleValue` argument if
* it is an `AnimatedValue` or the closest `AnimatedValue` parent
* if it isn't.
*
* @param styleValue The style value to remove the listener from.
* @param listenerId The id of the listener to remove.
*/
export const removeAnimatedValueListener = (styleValue, listenerId) => {
const animatedValue = findAnimatedValue(styleValue);
if (animatedValue) {
animatedValue.removeListener(listenerId);
}
};

0 comments on commit 6fbac78

Please sign in to comment.