-
-
Save virusvn/2a97cdb9fb2248bea75c3337b2d067fa to your computer and use it in GitHub Desktop.
react-native requestAnimationFrame and d3-interpolate
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
//this is an example of background animation from my weather comparsion app | |
//you can get early build of app at http://zowni.com | |
//full source of background.js below | |
const React = require('react'); | |
const Svg = React.createFactory(require('react-native-svg').Svg); | |
const {interpolate} = require('d3-interpolate'); | |
//... | |
/** | |
* functions which returns color stop | |
* @returns {string[][]} colors | |
*/ | |
function getStops(hourly, hourRange, useApparentTemperature) { | |
//... | |
} | |
React.createClass({ | |
getInitialState() { | |
const {hourly, hourRange, useApparentTemperature} = this.props; | |
return { | |
stops: getStops(hourly, hourRange, useApparentTemperature) | |
}; | |
}, | |
componentWillReceiveProps(props) { | |
const { | |
hourly, | |
hourRange, | |
useApparentTemperature | |
} = props; | |
//create interpolator which will interpolate object (array of color stops this time) | |
//between current state and new state | |
const interpolator = interpolate( | |
this.state, | |
{stops: getStops(hourly, hourRange, useApparentTemperature)} | |
); | |
const start = Date.now(); | |
const duration = 500; | |
//define animation step | |
this._animation = () => { | |
const now = Date.now(); | |
let t = (now - start) / duration; | |
if (t > 1) { | |
t = 1; | |
} | |
//intepolator takes as input value from 0..1 | |
this.setState(interpolator(t)); | |
if (t < 1) { | |
//go to next animation step | |
requestAnimationFrame(this._animation); | |
} | |
} | |
//start animtion | |
requestAnimationFrame(this._animation); | |
}, | |
render () { | |
const {stops} = this.state; | |
//... | |
//just draw svg rect with gradients | |
return Svg( | |
//... | |
); | |
} | |
}); |
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
/** | |
* background gradient | |
* @module components/background | |
*/ | |
const React = require('react'); | |
const getDimensions = require('../lib/getDimensions'); | |
const Svg = React.createFactory(require('react-native-svg').Svg); | |
const Defs = React.createFactory(require('react-native-svg').Defs); | |
const Stop = React.createFactory(require('react-native-svg').Stop); | |
const connect = require('react-redux').connect; | |
const getColorByTemp = require('../lib/temperature-color'); | |
const getDataPoints = require('../lib/getDataPoints'); | |
const {interpolate} = require('d3-interpolate'); | |
const LinearGradient = React.createFactory( | |
require('react-native-svg').LinearGradient | |
); | |
const Rect = React.createFactory(require('react-native-svg').Rect); | |
/** | |
* @param {ForecastDataBlock[]} hourly | |
* @param {number[]} hourRange | |
* @param {boolean} useApparentTemperature | |
* @returns {string[][]} colors | |
*/ | |
function getStops(hourly, hourRange, useApparentTemperature) { | |
return hourly.map((dataBlock) => { | |
const points = getDataPoints(dataBlock); | |
if (points) { | |
let targetTempAr = points.map( | |
p => { | |
return useApparentTemperature ? | |
p.apparentTemperature : | |
p.temperature; | |
} | |
); | |
let maxTemp = Math.max(...targetTempAr.slice(...hourRange)); | |
let minTemp = Math.min(...targetTempAr.slice(...hourRange)); | |
return [ | |
getColorByTemp(maxTemp), | |
getColorByTemp(minTemp) | |
] | |
} else { | |
return [ | |
'rgb(84, 84, 84)', | |
'rgb(84, 84, 84)' | |
]; | |
} | |
}); | |
} | |
module.exports = connect( | |
(state) => { | |
return { | |
hourRange: state.hourRange, | |
hourly: state.hourly, | |
useApparentTemperature: state.useApparentTemperature | |
} | |
} | |
)(React.createClass({ | |
getInitialState() { | |
const {hourly, hourRange, useApparentTemperature} = this.props; | |
return { | |
stops: getStops(hourly, hourRange, useApparentTemperature) | |
}; | |
}, | |
componentWillReceiveProps(props) { | |
const { | |
hourly, | |
hourRange, | |
useApparentTemperature | |
} = props; | |
const interpolator = interpolate( | |
this.state, | |
{stops: getStops(hourly, hourRange, useApparentTemperature)} | |
); | |
const start = Date.now(); | |
const duration = 500; | |
this._animation = () => { | |
const now = Date.now(); | |
let t = (now - start) / duration; | |
if (t > 1) { | |
t = 1; | |
} | |
this.setState(interpolator(t)); | |
if (t < 1) { | |
requestAnimationFrame(this._animation); | |
} | |
} | |
requestAnimationFrame(this._animation); | |
}, | |
render () { | |
const padding = 0; | |
let {width, curveHeight, viewHeight} = getDimensions(); | |
width += 2 * padding; | |
const {stops} = this.state; | |
return Svg( | |
{ | |
width, | |
height: viewHeight, | |
style: { | |
position: 'absolute', | |
left: -padding | |
} | |
}, | |
Defs(null, | |
LinearGradient( | |
{ | |
id: 'grad1', | |
x1: 0, | |
y1: 0, | |
x2: 0, | |
y2: viewHeight | |
}, | |
Stop({ | |
offset: String(1 - curveHeight / viewHeight), | |
stopColor: stops[0][0], | |
stopOpacity: 1 | |
}), | |
Stop({ | |
offset: String(1), | |
stopColor: stops[0][1], | |
stopOpacity: 1 | |
}) | |
), | |
LinearGradient( | |
{ | |
id: 'grad2', | |
x1: 0, | |
y1: 0, | |
x2: 0, | |
y2: viewHeight | |
}, | |
Stop({ | |
offset: String(1 - curveHeight / viewHeight), | |
stopColor: stops[1][0], | |
stopOpacity: 1 | |
}), | |
Stop({ | |
offset: String(1), | |
stopColor: stops[1][1], | |
stopOpacity: 1 | |
}) | |
) | |
), | |
Rect({x: 0, y: 0, width: width / 2, height: viewHeight, fill: 'url(#grad1)'}), | |
Rect({x: width/2, y: 0, width: width / 2, height: viewHeight, fill: 'url(#grad2)'}) | |
); | |
} | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment