$30 off During Our Annual Pro Sale. View Details »

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. Draw Animated Chart on
    React Native
    (from scratch)
    @shuheikagawa

    View Slide

  2. 1. div & CSS
    2. Animation
    3. React ART
    4. Animation again

    View Slide

  3. Me
    → Software Engineer at M3, Inc.
    → AngularJS, Rails, Babel, etc.
    → GitHub, Qiita: @shuhei
    → Twitter: @shuheikagawa

    View Slide

  4. EcmaScript & Me
    Stage 0 Method Parameter Decorators
    -> babel/babylon
    @Component({ /* ... */ })
    class App {
    constructor(@Inject('something') foo) {
    }
    }

    View Slide

  5. React Native

    View Slide

  6. View Slide

  7. View Slide

  8. 23°?

    View Slide

  9. I only remember yesterday's temperature

    View Slide

  10. Let's compare!

    View Slide

  11. View Slide

  12. There are some iOS/Android-only libraries, but.....
    → tomauty/react-native-chart
    → Jpadilla1/react-native-ios-charts
    → hongyin163/react-native-chart-android

    View Slide

  13. Let’s drawing charts in React-Native without any
    library
    by WangZixiao

    View Slide

  14. ==

    View Slide

  15. → Flexbox: A Complete Guide to Flexbox
    → position: absolute;

    View Slide

  16. View Slide


  17. styles.barPast]} />
    styles.barFuture]} />

    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
    }
    });

    View Slide

  18. const bars = days.map((day, i) =>




    );

    {bars}

    const styles = StyleSheet.create({
    container: {
    alignItems: 'flex-end',
    flexDirection: 'row',
    },
    barBox: {
    width: 10,
    marginHorizontal: 2,
    alignItems: 'flex-end',
    flexDirection: 'row',
    }
    });

    View Slide

  19. Animation in React Native
    → Explicit: Animated
    → Implicit: LayoutAnimation

    View Slide

  20. 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 => );
    return {bars};
    }
    // ...
    }

    View Slide

  21. 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();
    }
    }

    View Slide

  22. View Slide

  23. Not so bad.

    View Slide

  24. View Slide

  25. LayoutAnimation
    // Somewhere in a container component...
    LayoutAnimation.spring();
    this.setState({ ...whatever });
    // Just render as if no animation.
    function TemperatureBar({ temperature }) {
    return
    }

    View Slide

  26. But I want curves...

    View Slide

  27. gl-react-native?

    View Slide

  28. gl-react-native?
    It's only for effects with shaders!

    View Slide

  29. react-art!
    → SVG-like vector graphics API on React
    → Canvas, SVG, VML (IE8), React Native, etc.

    View Slide

  30. import {
    Surface,
    Shape
    } from 'ReactNativeART';
    function Square() {
    const d = Path()
    .moveTo(100, 100)
    .lineTo(200, 100)
    .lineTo(200, 200)
    .lineTo(100, 200)
    .close();
    return

    ;
    }

    View Slide

  31. 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

    ;
    }

    View Slide

  32. View Slide

  33. Path animation
    Before:


    ;
    After:
    const AnimatedShape = Animated.createAnimatedComponent(Shape);


    ;

    View Slide

  34. d is made of multiple heights.
    // Non-animated
    (heights: number[]) => Path
    // Animated
    (animatedHeights: Animated[]) => Animated

    View Slide

  35. // We have:
    Animated.add, Animated.multiply:
    (a: Animated, b: Animated) => Animated
    // We want:
    Animated.aggregate:
    (xs: Animated[], f: (number[]) => T) => Animated

    View Slide

  36. View Slide

  37. View Slide

  38. const animatedHeights = Array.from(Array(24))
    .map(() => new Animated.Value(0));
    const animatedPath = aggregate(
    animatedHeights,
    heights => areaChartPath(CHART_WIDTH, CHART_HEIGHT, heights)
    );

    View Slide

  39. View Slide

  40. View Slide

  41. 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

    View Slide

  42. Thanks!
    https://github.com/shuhei/Compare

    View Slide