Last active
August 29, 2015 14:11
-
-
Save OlavHN/987bc0469bc501621b4f to your computer and use it in GitHub Desktop.
Drag to animation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = { | |
dragStart: function(state, onEnd) { | |
// We'll run the entire drag loop in this scope! | |
var component = this; | |
function getInput(evt) { | |
var evtObj = 'ontouchstart' in window ? evt.changedTouches[0] : evt; | |
return {x: evtObj.clientX, y: evtObj.clientY}; | |
} | |
function dragMove(evt) { | |
evt.preventDefault(); | |
// Update internal stuff | |
var input = getInput(evt); | |
var pos = { | |
x: input.x - state.offset.x, | |
y: input.y - state.offset.y | |
}; | |
var dPos = { | |
x: pos.x - state.position.x, | |
y: pos.y - state.position.y | |
}; | |
state.position = pos; | |
var dTime = Date.now() - state.time; | |
state.time = Date.now(); | |
state.velocity = { | |
x: 0.8 * 1000 * dPos.x / (1 + dTime) + 0.2 * state.velocity.x, | |
y: 0.8 * 1000 * dPos.y / (1 + dTime) + 0.2 * state.velocity.y | |
}; | |
// Update state | |
var stateObj = {}; | |
stateObj[state.name] = { | |
position: state.position, | |
velocity: state.velocity | |
}; | |
component.setState(stateObj); | |
} | |
function dragEnd(evt) { | |
evt.preventDefault(); | |
document.removeEventListener('touchmove', dragMove); | |
document.removeEventListener('touchend', dragEnd); | |
document.removeEventListener('mousemove', dragMove); | |
document.removeEventListener('mouseup', dragEnd); | |
if (typeof onEnd === 'function') | |
onEnd(); | |
} | |
return function(evt) { | |
evt.preventDefault(); | |
var name = state.name ? state.name : state; | |
var input = getInput(evt); | |
var position; | |
if (component.state[name]) | |
position = component.state[name].position; | |
else { | |
var rect = component.getDOMNode().getBoundingClientRect(); | |
position = {x: rect.left, y: rect.top}; | |
} | |
var offset = { | |
x: input.x - position.x, | |
y: input.y - position.y | |
}; | |
// Hijack the reference as it's perfectly scoped! | |
state = { | |
name: state.name ? state.name : state, | |
offset: offset, | |
position: position, | |
velocity: {x: 0, y: 0}, | |
time: Date.now() | |
}; | |
// Update state | |
var stateObj = {}; | |
stateObj[state.name] = { | |
position: state.position, | |
velocity: state.velocity | |
}; | |
component.setState(stateObj); | |
document.addEventListener('touchmove', dragMove); | |
document.addEventListener('touchend', dragEnd); | |
document.addEventListener('mousemove', dragMove); | |
document.addEventListener('mouseup', dragEnd); | |
}; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var React = require('react'); | |
var RCSS = require('rcss'); | |
var tweenState = require('react-tween-state'); | |
var DragMixin = require('./mixins/drag-mixin'); | |
var headerStyle = RCSS.registerClass({ | |
position: 'relative', | |
width: '100%', | |
background: 'rgba(0, 0, 0, 0.5)', | |
boxSizing: 'border-box' | |
}); | |
var headerBorderStyle = RCSS.registerClass({ | |
position: 'absolute', | |
bottom: 0 | |
}); | |
var Header = React.createClass({ | |
mixins: [ | |
tweenState.Mixin, | |
DragMixin | |
], | |
render: function() { | |
if (!this.props.device) | |
return null; | |
// Get current tweened value | |
var height = this.props.height; | |
var y = this.state.headerTween ? this.getTweeningValue(function(state) { return state.headerTween.position; }, 'y') : - height * 2 + 30; | |
var inlineStyle = { | |
WebkitTransform: 'translate3d(0, ' + y + 'px, 0)', | |
transform: 'translate3d(0, ' + y + 'px, 0)', | |
height: height * 2, | |
paddingTop: height | |
}; | |
var dragHandler = this.dragStart('headerTween', this.endDrag) | |
return ( | |
<div onMouseDown={dragHandler} onTouchStart={dragHandler} className={headerStyle.className} style={inlineStyle}> | |
<div className={headerBorderStyle.className}> | |
GONZO | |
</div> | |
</div> | |
); | |
}, | |
endDrag: function() { | |
var endPos = this.state.headerTween.position.y + 0.5 * this.state.headerTween.velocity.y; | |
var height = this.props.height; | |
// Animate either back up or all the way down | |
this.tweenState(function(state) { return state.headerTween.position}, 'y', { | |
initialVelocity: this.state.headerTween.velocity.y, | |
tension: 40, | |
friction: 5, | |
endValue: endPos > -height * 1.5 ? -height : -height * 2 + 30 | |
}); | |
} | |
}); | |
module.exports = Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
react-tween-state changes for rebound-js: | |
https://github.com/OlavHN/react-tween-state/commit/a4c2a09c1895c9ac1e73b74281d1bc491b30ec27 | |
Example: http://olavhn.github.io/react-tween-state/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gist.github.com/OlavHN/987bc0469bc501621b4f#file-header-jsx-L41
I realize that is really stupid .. It'll execute the entire function on each render .. Must be moved to a new part or have the function return cached results ..