Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Draw Animated Chart on React Native

Draw Animated Chart on React Native

Meguro.es #4

How to draw chart with only & StyleSheet like & CSS
How to draw chart with React ART
How to animate them

Shuhei Kagawa

June 21, 2016
Tweet

More Decks by Shuhei Kagawa

Other Decks in Programming

Transcript

  1. Me → Software Engineer at M3, Inc. → AngularJS, Rails,

    Babel, etc. → GitHub, Qiita: @shuhei → Twitter: @shuheikagawa
  2. EcmaScript & Me Stage 0 Method Parameter Decorators -> babel/babylon

    @Component({ /* ... */ }) class App { constructor(@Inject('something') foo) { } }
  3. <View style={[styles.barBox]}> <View style={[styles.bar, styles.barPast]} /> <View style={[styles.bar, styles.barFuture]} />

    </View> const styles = StyleSheet.create({ barBox: { alignItems: 'flex-end', flexDirection: 'row', }, bar: { width: 10, borderTopLeftRadius: 5, borderTopRightRadius: 5 }, barPast: { backgroundColor: 'gray' }, barFuture: { backgroundColor: '#bbccbbff' marginLeft: -10 } });
  4. const bars = days.map((day, i) => <View key={i} style={[styles.barBox]}> <View

    ... /> <View ... /> </View> ); <View style={styles.container}> {bars} </View> const styles = StyleSheet.create({ container: { alignItems: 'flex-end', flexDirection: 'row', }, barBox: { width: 10, marginHorizontal: 2, alignItems: 'flex-end', flexDirection: 'row', } });
  5. Animated class BarChart extends Component { constructor(props) { // Prepare

    *animated* value holders. this.state = { heights: props.heights.map(h => new Animated.Value(h)) }; } render() { // `Animated.View` subscribes to changes of *animated* value // and update underneath props. const bars = this.state.heights .map(h => <Animated.View style={[{ height: h }, otherStyle]} />); return <View>{bars}</View>; } // ... }
  6. componentWillReceiveProps(nextProps) { if (this.props.heights !== nextProps.heights) { // Trigger animation.

    const anims = this.state.heights .map((h, i) => Animated.spring(h, { toValue: nextProps.heights[i] })); Animated.parallel(anims).start(); } }
  7. LayoutAnimation // Somewhere in a container component... LayoutAnimation.spring(); this.setState({ ...whatever

    }); // Just render as if no animation. function TemperatureBar({ temperature }) { return <View style={[otherStyle, { height: temperatureToHeight(temperature) }]} /> }
  8. import { Surface, Shape } from 'ReactNativeART'; function Square() {

    const d = Path() .moveTo(100, 100) .lineTo(200, 100) .lineTo(200, 200) .lineTo(100, 200) .close(); return <Surface width={300} height={300}> <Shape fill="#000000" d={d} /> <Surface>; }
  9. function AreaChart({ width, height, points }) { let i =

    0; let path = Path().moveTo(0, h) .lineTo(0, points[i].y) .lineTo(points[i].x, points[i].y); for (i = 1; i < 24 - 2; i++) { const p = points[i]; const q = points[i + 1]; const xc = (p.x + q.x) / 2; const yc = (p.y + q.y) / 2; path = path.curveTo(p.x, p.y, xc, yc); } path = path .curveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y) .lineTo(CHART_WIDTH, points[i + 1].y); const d = path.lineTo(w, h).close(); return <Surface width={width} height={height}> <Shape fill="#ff9999" d={d} /> </Surface>; }
  10. Path animation Before: <Surface width={width} height={height}> <Shape fill="#ff9999" d={d} />

    </Surface>; After: const AnimatedShape = Animated.createAnimatedComponent(Shape); <Surface width={width} height={height}> <AnimatedShape fill="#ff9999" d={d} /> </Surface>;
  11. d is made of multiple heights. // Non-animated (heights: number[])

    => Path // Animated (animatedHeights: Animated<number>[]) => Animated<Path>
  12. // We have: Animated.add, Animated.multiply: (a: Animated<number>, b: Animated<number>) =>

    Animated<number> // We want: Animated.aggregate<T>: (xs: Animated<number>[], f: (number[]) => T) => Animated<T>
  13. const animatedHeights = Array.from(Array(24)) .map(() => new Animated.Value(0)); const animatedPath

    = aggregate( animatedHeights, heights => areaChartPath(CHART_WIDTH, CHART_HEIGHT, heights) );
  14. Recap → You can draw (almost) anything with View &

    CSS → LayoutAnimation is super easy → Draw curves with React ART → Path animation is feasible but (a bit) slow