Skip to content
This repository has been archived by the owner on Apr 9, 2019. It is now read-only.

Commit

Permalink
Added options.transitionFriction and options.transitionTension
Browse files Browse the repository at this point in the history
  • Loading branch information
aputinski committed Mar 30, 2015
1 parent 23dc6ac commit 084ae5d
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 27 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Build Status][travis-image]][travis-url]
[![NPM version][npm-image]][npm-url]

A React view manager similar to [UINavigationController][ios-controller]
React view manager similar to [UINavigationController][ios-controller]

## Instalation

Expand Down Expand Up @@ -128,6 +128,14 @@ navigationController.pushView(<MyView />, {
});
```

##### `options.transitonTension` `{number}` `default=10`

Specify the spring tension to be used for built-in animations

##### `options.transitonFriction` `{number}` `default=6`

Specify the spring friction to be used for built-in animations

##### `options.onComplete` `{function}`

Called once the transition has completed
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-navigation-controller",
"version": "1.0.1",
"description": "A React view manager similar to UINavigationController",
"version": "1.0.2",
"description": "React view manager similar to UINavigationController",
"keywords": [
"react",
"react-component"
Expand Down
47 changes: 29 additions & 18 deletions spec/navigation-controller.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,15 @@ describe('NavigationController', () => {
});
});
it('sets the completion callback', () => {
controller.__transitionViews(null, () => {});
controller.__transitionViews({});
expect(controller.__transitionViewsComplete).to.be.a('function');
});
it('sets and calls the completion callback', (done) => {
const transitionCallbackSpy = sinon.spy();
controller.__transitionViews(Transition.type.NONE, transitionCallbackSpy);
controller.__transitionViews({
transition: Transition.type.NONE,
onComplete: transitionCallbackSpy
});
const transitionCompleteSpy = sinon.spy(controller, '__transitionViewsComplete');
requestAnimationFrame(() => {
expect(transitionCompleteSpy.calledOnce).to.be.true;
Expand All @@ -312,7 +315,9 @@ describe('NavigationController', () => {
it('manually runs a "none" transition', (done) => {
const transformSpy = sinon.spy(controller, '__transformViews');
const animateCompleteSpy = sinon.spy(controller, '__animateViewsComplete');
controller.__transitionViews(Transition.type.NONE);
controller.__transitionViews({
transition: Transition.type.NONE
});
const transitionCompleteSpy = sinon.spy(controller, '__transitionViewsComplete');
requestAnimationFrame(() => {
expect(transformSpy.calledOnce).to.be.true;
Expand All @@ -325,26 +330,32 @@ describe('NavigationController', () => {
const animateSpy = sinon.spy(controller, '__animateViews');
const transformSpy = sinon.spy(controller, '__transformViews');
const animateCompleteSpy = sinon.spy(controller, '__animateViewsComplete');
controller.__transitionViews(Transition.type.PUSH_LEFT, function() {
expect(animateSpy.callCount).to.be.above(1);
expect(transformSpy.callCount).to.be.above(1);
expect(animateCompleteSpy.calledOnce).to.be.true;
done();
controller.__transitionViews({
transition: Transition.type.PUSH_LEFT,
onComplete() {
expect(animateSpy.callCount).to.be.above(1);
expect(transformSpy.callCount).to.be.above(1);
expect(animateCompleteSpy.calledOnce).to.be.true;
done();
}
});
controller.__isTransitioning = true;
});
it('runs a custom transtion', (done) => {
let _prevElement,_nextElement;
controller.__transitionViews((prevElement, nextElement, done) => {
_prevElement = prevElement;
_nextElement = nextElement;
prevElement.style[transformPrefix] = 'translate3d(10px, 20px, 0px)';
nextElement.style[transformPrefix] = 'translate3d(30px, 40px, 0px)';
setTimeout(done, 500);
}, () => {
expect(_prevElement.style[transformPrefix]).to.equal(`translate3d(10px, 20px, 0px)`);
expect(_nextElement.style[transformPrefix]).to.equal(`translate3d(30px, 40px, 0px)`);
done();
controller.__transitionViews({
transition(prevElement, nextElement, done) {
_prevElement = prevElement;
_nextElement = nextElement;
prevElement.style[transformPrefix] = 'translate3d(10px, 20px, 0px)';
nextElement.style[transformPrefix] = 'translate3d(30px, 40px, 0px)';
setTimeout(done, 500);
},
onComplete() {
expect(_prevElement.style[transformPrefix]).to.equal(`translate3d(10px, 20px, 0px)`);
expect(_nextElement.style[transformPrefix]).to.equal(`translate3d(30px, 40px, 0px)`);
done();
}
});
});
});
Expand Down
36 changes: 30 additions & 6 deletions src/navigation-controller.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const React = require('react');

const rebound = require('rebound');
const {
SpringSystem,
SpringConfig,
OrigamiValueConverter
} = rebound;
const {
mapValueInRange
} = rebound.MathUtil;
Expand Down Expand Up @@ -89,7 +94,7 @@ class NavigationController extends React.Component {
this.__isTransitioning = false;
this.__viewStates = [];
this.__viewIndexes = [0,1];
this.__springSystem = new rebound.SpringSystem();
this.__springSystem = new SpringSystem();
this.__spring = this.__springSystem.createSpring(
this.props.transitionTension,
this.props.transitionFriction
Expand Down Expand Up @@ -229,7 +234,20 @@ class NavigationController extends React.Component {
* @param {string} transition
* @param {function} [onComplete] - Called once the transition is complete
*/
__transitionViews(transition, onComplete) {
__transitionViews(options) {
options = typeof options === 'object' ? options : {};
const defaults = {
transitionTension: this.props.transitionTension,
transitionFriction: this.props.transitionFriction
};
options = assign({}, defaults, options);
const {
transition,
transitionTension,
transitionFriction,
onComplete
} = options;
// Create a function that will be called once the
this.__transitionViewsComplete = () => {
delete this.__transitionViewsComplete;
if (typeof onComplete === 'function') {
Expand All @@ -250,6 +268,12 @@ class NavigationController extends React.Component {
}
// Otherwise use the springs
else {
this.__spring.setSpringConfig(
new SpringConfig(
OrigamiValueConverter.tensionFromOrigamiValue(transitionTension),
OrigamiValueConverter.frictionFromOrigamiValue(transitionFriction)
)
);
this.__spring.setEndValue(1);
}
}
Expand Down Expand Up @@ -295,7 +319,7 @@ class NavigationController extends React.Component {
options = assign({}, defaults, options, { view });
checkOptions('pushView', options);
if (this.__isTransitioning) return;
const {transition,onComplete} = options;
const {transition} = options;
const [prev,next] = this.__viewIndexes;
let views = this.state.views.slice();
// Alternate mounted views order
Expand All @@ -319,7 +343,7 @@ class NavigationController extends React.Component {
this.__viewStates.push(prevView.state);
}
// Transition
this.__transitionViews(transition, onComplete);
this.__transitionViews(options);
});
this.__isTransitioning = true;
}
Expand All @@ -342,7 +366,7 @@ class NavigationController extends React.Component {
throw new Error('popView() can only be called with two or more views in the stack')
};
if (this.__isTransitioning) return;
const {transition,onComplete} = options;
const {transition} = options;
const [prev,next] = this.__viewIndexes;
const views = dropRight(this.state.views);
// Alternate mounted views order
Expand All @@ -368,7 +392,7 @@ class NavigationController extends React.Component {
}
}
// Transition
this.__transitionViews(transition, onComplete);
this.__transitionViews(options);
});
this.__isTransitioning = true;
}
Expand Down

0 comments on commit 084ae5d

Please sign in to comment.