Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Avatar for Shuhei Kagawa

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