Skip to content

Multi transitions #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 104 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
224c303
Add transition view classes
lintonye Feb 19, 2017
46c5e57
Merge branch 'master' into multi-transitions
lintonye Feb 19, 2017
cef903a
Wrap SceneView in Transition.View
lintonye Feb 20, 2017
7768e99
TransitionView: clone as animated component
lintonye Feb 20, 2017
51c2e8f
SceneView: Revert to master
lintonye Feb 21, 2017
e5163f8
Add a crossfade transition to playground
lintonye Feb 21, 2017
4b9babd
Convert Card to Transition.View
lintonye Feb 21, 2017
7f786e0
Add builtin transition components
lintonye Feb 21, 2017
750a3f0
Remove TransitionView
lintonye Feb 21, 2017
91d0fe4
Remove original animated style assigned to Card
lintonye Feb 21, 2017
098f161
Use prevRouteName and routeName to find transition
lintonye Feb 21, 2017
d35ee95
Revert "Add a crossfade transition to playground"
lintonye Feb 21, 2017
99212c5
Add initial shared element transition example to playground
lintonye Feb 21, 2017
255e2a7
Add Transition.Text
lintonye Feb 21, 2017
f2ea7f9
Export Transition
lintonye Feb 21, 2017
7378a54
Add faker dependency
lintonye Feb 21, 2017
312ef2d
Temporary: Use Transition examples as Playground entry
lintonye Feb 21, 2017
2955f0a
Update yarn.lock as the result of "yarn add faker"
lintonye Feb 21, 2017
05d11f1
Apply filter before creating transition style
lintonye Feb 21, 2017
165956a
Remove logging
lintonye Feb 21, 2017
d3502bd
name => id, containerRouteName => routeName
lintonye Feb 21, 2017
53a1af7
Use CrossFade for now
lintonye Feb 21, 2017
918333e
Register/unregister transition items
lintonye Feb 21, 2017
37a2016
_hideTransitionViewUntilDone
lintonye Feb 21, 2017
2f20998
Invoke transitions in a batch
lintonye Feb 22, 2017
e914fde
Comment out unused code
lintonye Feb 22, 2017
16bb0b9
Fix error from PointerEventsContainer
lintonye Feb 22, 2017
19ad1bc
Comment out useless function
lintonye Feb 22, 2017
a4851ef
Remove unused code
lintonye Feb 22, 2017
e7a1f57
Add CustomTransitions to root navigator
lintonye Feb 22, 2017
d2aac8c
Hide transition views if should clone
lintonye Feb 22, 2017
9284a27
Default transitions (incomplete)
lintonye Feb 22, 2017
ee20d5e
Implement shared element transition
lintonye Feb 22, 2017
f9bce37
Measure views on layout (error: view not found)
lintonye Feb 22, 2017
0447e53
Merge branch 'master' into multi-transitions
lintonye Feb 22, 2017
61bca7c
Removed outdated comments
lintonye Feb 22, 2017
c06cca0
Remove unused code
lintonye Feb 22, 2017
5e8cb78
Properly validate metrics; update logs
lintonye Feb 24, 2017
765c344
Don't create animated components for existing animated views
lintonye Feb 24, 2017
3ea7d0f
Refactoring; clone items
lintonye Feb 25, 2017
eb62665
Make sure transition is getting called
lintonye Feb 25, 2017
f2f2bc2
Properly create inPlaceStyleMap
lintonye Feb 25, 2017
d3d8264
Determine if an item should be cloned in batch
lintonye Feb 25, 2017
5a99f1f
Updated comments
lintonye Feb 26, 2017
d509ea4
Shared element back now works
lintonye Feb 27, 2017
302c3ec
Make longer description to test scroll position
lintonye Feb 27, 2017
4370c98
Update only if all items are meatured
lintonye Feb 27, 2017
f477f48
Manually call onLayout when back from a scene
lintonye Feb 27, 2017
f5c50d7
Reset metrics from componentWillReceiveProps
lintonye Feb 27, 2017
e23818f
getItemsToClone to return array instead of map
lintonye Feb 27, 2017
3ccc3d5
Refactoring: extract _getFilteredFromToItems
lintonye Feb 27, 2017
5415287
Only measure necessary items
lintonye Feb 27, 2017
97dd4b1
setShouldMeasure in onLayout (both transitions work now)
lintonye Feb 27, 2017
d1f56db
Refactoring: split createTransitionStyleMaps
lintonye Feb 27, 2017
4cfee85
Refactoring: always use "fromRoute, toRoute" convention
lintonye Feb 28, 2017
8b4ee0e
Remove used code
lintonye Feb 28, 2017
b6bcda8
Hide overlay after transition
lintonye Feb 28, 2017
b662b46
Fix crash when getItemsToClone is not specified
lintonye Feb 28, 2017
1656c8f
Use subscription to enable context propagation
lintonye Feb 28, 2017
674be98
Disable logging
lintonye Feb 28, 2017
cc31681
Add simple composition function together
lintonye Feb 28, 2017
235c9ee
Add test logging
lintonye Feb 28, 2017
d359c13
Extract _setTransitionItemsState
lintonye Feb 28, 2017
9d891b6
composition: apply filter before sending to child transitions
lintonye Feb 28, 2017
038bd05
Add staggeredAppear example
lintonye Feb 28, 2017
bcd737c
Remove unused files
lintonye Feb 28, 2017
6a33411
Remove storehouse incomplete code
lintonye Feb 28, 2017
47ee3e5
Extract SharedElement to its own file
lintonye Mar 4, 2017
911e40c
Disable default transition to avoid error when installed from npm
lintonye Mar 4, 2017
b7bd217
Set the opacity of the outgoing scene to 0 by default to prevent over…
lintonye Mar 4, 2017
fcee4b5
Add listview to PhotoDetail to help debug perf issue
lintonye Mar 4, 2017
8966e70
Perf: avoid unnecesary state updates when onLayout is called
lintonye Mar 4, 2017
defd7a2
prevent unnecesary updates when registering/unregistering transition …
lintonye Mar 4, 2017
3c837ce
Add NoOp transition for testing
lintonye Mar 4, 2017
b9db6f9
By default, hide incoming scene until transition is done
lintonye Mar 4, 2017
5d32e47
Prevent overdraw when transition ends
lintonye Mar 4, 2017
da30ab3
Comment out logging
lintonye Mar 5, 2017
3008a68
Only call transitions when all items are measured
lintonye Mar 5, 2017
8280995
Add unit test for TransitionItems
lintonye Mar 5, 2017
9ffd5e6
Interpolate using position
lintonye Mar 7, 2017
9d0fc1c
inputRange default to [0, 1]
lintonye Mar 7, 2017
c2a9c07
Sequence that merge different props
lintonye Mar 8, 2017
61c5b45
Update SharedElement using composition
lintonye Mar 8, 2017
fe9da74
Add unit tests
lintonye Mar 8, 2017
bc228d7
Fix syntax errors
lintonye Mar 8, 2017
49f5cad
Fix CardStack errors
lintonye Mar 8, 2017
7dc866f
Add null checks
lintonye Mar 8, 2017
997dac8
Make sure the full [0, 1] inputRange is covered to avoid accidental o…
lintonye Mar 8, 2017
c3b2660
Compute duration for together
lintonye Mar 8, 2017
97ca27d
Add TODO
lintonye Mar 8, 2017
967e1c6
Add more precision to inputRange of styles that hide overlay and tran…
lintonye Mar 8, 2017
694e3c2
Add SharedElement transition that actually look good
lintonye Mar 8, 2017
43b4a60
Extract CrossFade into Transitions
lintonye Mar 8, 2017
2ebac4e
Fix flickering
lintonye Mar 8, 2017
d2747a7
Add Scale transition
lintonye Mar 8, 2017
1c9eadd
Configure canUseNativeDriver
lintonye Mar 8, 2017
60ffce1
Make duration etc configurable
lintonye Mar 8, 2017
cedfa82
Process transform when converting style maps
lintonye Mar 8, 2017
6176803
Scale to actually use 'scale'
lintonye Mar 8, 2017
f7c6d44
createAnimatedStyleMap => createStyleMap
lintonye Mar 8, 2017
80cc59d
Merge branch 'master' into multi-transitions
lintonye Mar 9, 2017
96c2920
createStyleMap => getStyleMap
lintonye Mar 12, 2017
8574fbf
Merge branch 'master' into multi-transitions
lintonye Mar 25, 2017
f2661bf
Add back UIManager import
lintonye Mar 25, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion examples/NavigationPlayground/js/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ModalStack from './ModalStack';
import StacksInTabs from './StacksInTabs';
import SimpleStack from './SimpleStack';
import SimpleTabs from './SimpleTabs';
import Transitions from './Transitions';

const ExampleRoutes = {
SimpleStack: {
Expand Down Expand Up @@ -63,6 +64,12 @@ const ExampleRoutes = {
screen: SimpleTabs,
path: 'settings',
},
Transitions: {
name: 'Custom Transitions',
description: 'Custom, complex transitions',
screen: Transitions,
path: 'transitions',
},
};

const MainScreen = ({ navigation }) => (
Expand Down Expand Up @@ -103,7 +110,8 @@ const AppNavigator = StackNavigator({
mode: Platform.OS === 'ios' ? 'modal' : 'card',
});

export default () => <AppNavigator />;
// export default () => <AppNavigator />;
export default Transitions; // TODO change it back

const styles = StyleSheet.create({
item: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// @flow
import React, { Component } from 'react';
import {
View,
ScrollView,
Image,
StyleSheet,
Animated,
Dimensions,
Text,
Easing,
ListView,
} from 'react-native';

import { Transition } from 'react-navigation';

import Touchable from './Touchable';

const { width: windowWidth } = Dimensions.get("window");

const PhotoDetail = (props) => {
const { photo } = props.navigation.state.params;
const { url, title, description, image, comments } = photo;
const openMoreDetails = photo => props.navigation.navigate('PhotoMoreDetail', { photo });
const renderHeader = () => (
<View>
<Transition.Image id={`image-${url}`} source={image} style={styles.image} />
<View style={styles.titleContainer} onLayout={this._onLayout}>
<Text style={[styles.text, styles.title]}>{title}</Text>
</View>
<Text style={[styles.text]}>{description}</Text>
</View>
);
return (
<View>
<ListView dataSource={dsComments.cloneWithRows(comments)}
renderRow={renderComment}
renderHeader={renderHeader}
/>
</View>
)
};

PhotoDetail.navigationOptions = {
title: 'Photo Detail'
}

const renderComment = ({ author, comment, avatar, time }) => (
<View style={commentStyles.container}>
<View style={commentStyles.textContainer}>
<View style={commentStyles.authorContainer}>
<Text>{author}</Text>
<Text>{time}</Text>
</View>
<Text style={commentStyles.text}>{comment}</Text>
</View>
</View>
);

const dsComments = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
});


const styles = StyleSheet.create({
image: {
width: windowWidth,
height: windowWidth / 2,
},
title: {
fontSize: 35,
fontWeight: 'bold',
},
text: {
margin: 15,
}
});

const commentStyles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
marginLeft: 16,
marginRight: 16,
height: 72,
},
textContainer: {
flex: 1,
},
text: {
},
authorContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
}
});

export default PhotoDetail;
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// @flow
import React, { Component } from 'react';
import {
ListView,
Image,
View,
Text,
Dimensions,
StyleSheet,
} from 'react-native';
import faker from 'faker';
import _ from 'lodash';

import { Transition } from 'react-navigation';
import Touchable from './Touchable';

const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
});

const images = [
require('./images/img1.jpg'),
require('./images/img2.jpg'),
require('./images/img3.jpg'),
require('./images/img4.jpg'),
require('./images/img5.jpg'),
require('./images/img6.jpg'),
require('./images/img7.jpg'),
require('./images/img8.jpg'),
require('./images/img9.jpg'),
require('./images/img10.jpg'),
require('./images/img11.jpg'),
require('./images/img12.jpg'),
]

const photos = Array(50).fill(0).map(_ => ({
url: faker.image.animals(500, 500, true),
image: images[faker.random.number(images.length - 1)],
title: faker.name.findName(),
description: faker.lorem.paragraphs(10),
comments: Array(20).fill(0).map(_ => (
{
author: faker.name.findName(),
// avatar: avatars[faker.random.number(4)],
comment: faker.lorem.sentence(),
time: '12/21/2017',
}
))
}));

const colCount = 3;

const { width: windowWidth } = Dimensions.get("window");
const margin = 2;
const photoWidth = (windowWidth - margin * colCount * 2) / colCount;

const photoRows = _.chunk(photos, colCount);

class PhotoGrid extends Component {
static navigationOptions = {
title: 'Photo Grid'
}
render() {
return (
<ListView
dataSource={ds.cloneWithRows(photoRows)}
renderRow={this.renderRow.bind(this)}
/>);
}
renderRow(photos) {
return (
<View style={styles.row}>
{photos.map(this.renderCell.bind(this))}
</View>
)
}
renderCell(photo) {
const onPhotoPressed = photo => this.props.navigation.navigate('PhotoDetail', { photo });
return (
<Touchable onPress={() => onPhotoPressed(photo)} key={photo.url}>
<View style={styles.cell}>
<Transition.Image id={`image-${photo.url}`}
source={photo.image} style={styles.image} />
</View>
</Touchable>
)
}
}

const styles = StyleSheet.create({
row: {
flexDirection: 'row',
},
cell: {
margin: 2,
},
image: {
width: photoWidth,
height: photoWidth,
}
})

export default PhotoGrid;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import {
TouchableNativeFeedback,
TouchableOpacity,
Platform,
} from 'react-native';

const Touchable = props => {
const Comp = (Platform.OS === 'android'
? TouchableNativeFeedback
: TouchableOpacity);
return <Comp {...props} />
}

export default Touchable;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions examples/NavigationPlayground/js/Transitions/SharedElements/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {
StackNavigator,
} from 'react-navigation';

import PhotoGrid from './PhotoGrid';
import PhotoDetail from './PhotoDetail';
import { Transition } from 'react-navigation';
import _ from 'lodash';
import faker from 'faker';

const {createTransition, initTransition, together, sq, Transitions} = Transition;

const Slide = createTransition({
getStyleMap(
itemsOnFromRoute: Array<*>,
itemsOnToRoute: Array<*>,
transitionOptions,
) {
// direction is 1 or -1
const { direction, layout: {initWidth} } = transitionOptions;
const routeToSlide = direction > 0 ? 'to' : 'from';
const itemsToSlide = direction > 0 ? itemsOnToRoute : itemsOnFromRoute;
const slide = (result, item) => {
result[item.id] = {
translateX: {
// inputRange: [0, 1] /// ===> [position, nextPosition]
outputRange: (direction > 0
? [initWidth, 0]
: [0, initWidth]
)
}
}
return result;
}
return {
[routeToSlide]: itemsToSlide.reduce(slide, {}),
}
}
});

const SharedImage = initTransition(Transitions.SharedElement, /image-.+/);
const CrossFadeScene = initTransition(Transitions.CrossFade, /\$scene.+/);
const SlideScene = initTransition(Slide, /\$scene.+/);

const StaggeredAppear = (filter) => ({
filter,
getStyleMap(
itemsOnFromRoute: Array<*>,
itemsOnToRoute: Array<*>,
transitionProps) {
const createStyle = (startTime, axis, direction) => {
const {progress} = transitionProps;
const inputRange = [0, startTime, 1];
const opacity = progress.interpolate({
inputRange,
outputRange: [0, 0, 1],
});
const translate = progress.interpolate({
inputRange,
outputRange: [ direction * 400, direction * 400, 0],
});
axis = axis === 'x' ? 'translateX' : 'translateY';
return {
opacity,
transform: [ { [axis]: translate } ],
};
}
const clamp = (x, min, max) => Math.max(min, Math.min(max, x));
const axes = ['x', 'y'];
const directions = [-1, 1];
return {
to: itemsOnToRoute.reduce((result, item) => {
const startTime = clamp(Math.random(), 0.1, 0.9);
const axis = faker.random.arrayElement(axes);
const direction = faker.random.arrayElement(directions);
result[item.id] = createStyle(startTime, axis, direction);
return result;
}, {}),
};
}
})

// const StaggeredAppearImages = createTransition(StaggeredAppear, /image-.+/);

const NoOp = (filter) => ({
filter,
getStyleMap() {
console.log('NoOp transition called');
}
});
const NoOpImage = createTransition(NoOp, /image-.+/);

const transitions = [
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: CrossFadeScene(1) },
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: CrossFadeScene(1) },
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: NoOpImage},
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: NoOpImage},
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: together(SharedImage, DelayedFadeInDetail)},
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: together(SharedImage, FastFadeOutDetail) },
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: DelayedFadeInDetail},
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: FastFadeOutDetail },
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: SharedImage(1)},
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: SharedImage(1)},
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: CrossFadeScene },
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: together(StaggeredAppearImages, SlideScenes) },
// { from: 'PhotoGrid', to: 'PhotoDetail', transition: together(SharedImage(), sq(Idle(0.9), CrossFadeScene()))},
// { from: 'PhotoDetail', to: 'PhotoGrid', transition: together(CrossFadeScene(0.1), SharedImage())},
{ from: 'PhotoGrid', to: 'PhotoDetail', transition: sq(SharedImage(0.9), CrossFadeScene(0.1)), config: {duration: 650}},
{ from: 'PhotoDetail', to: 'PhotoGrid', transition: sq(CrossFadeScene(0.1), SharedImage(0.9)), config: {duration: 650}},
];

const App = StackNavigator({
PhotoGrid: {
screen: PhotoGrid,
},
PhotoDetail: {
screen: PhotoDetail,
}
}, {
transitions,
});

export default App;
4 changes: 4 additions & 0 deletions examples/NavigationPlayground/js/Transitions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SharedElements from './SharedElements';

// TODO export a navigator
export default SharedElements;
1 change: 1 addition & 0 deletions examples/NavigationPlayground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@exponent/vector-icons": "~4.0.0",
"exponent": "~13.1.0",
"faker": "^4.0.0",
"react": "~15.4.2",
"react-native": "github:exponent/react-native#sdk-13.0.0",
"react-native-vector-icons": "^4.0.0"
Expand Down
Loading