sghall / resonance

:black_medium_small_square:Resonance | 5kb React animation library
https://sghall.github.io/resonance
MIT License
1k stars 27 forks source link

Pie Chart example #22

Closed YouriT closed 7 years ago

YouriT commented 7 years ago

Hi @sghall !

As promised, I put up a small PR together to add a PieChart example to your docs :)

The things I did different:

As an improvement, it could be a small app with selectors and stuff like you did on the more complex examples. But I thought it is better to Keep It Simple and Stupid to ease understanding of readers as I personally add some troubles understanding the Sunburst example.

By the way I added webpack in the devDeps as it was not (in the docs).

Hope you will like it and again thanks for #21

Closes #21

YouriT commented 7 years ago

About the travis-ci. It's complaining about buffer-shims which is in the lock file but isn't in any requirement so this must have failed earlier than this PR no?

sghall commented 7 years ago

Looks good 👍. Thanks for sending this. Yeah, I'll look at the Travis issue. Not sure what's going on there :) I need to update a bunch of stuff this weekend. So, I made some comments. If you want to send an update that would be great. If not I can merge what you have in the next day or two and make some tweaks. I went over your code and just tried to quickly deal with the issues I pointed out. I also changed the colors because it's hard to see the different arcs. This is what I have...

import { interpolate } from 'd3-interpolate';
import { scaleOrdinal } from 'd3-scale';
import { arc, pie } from 'd3-shape';

import Surface from 'docs/src/components/Surface';
import React, { PureComponent } from 'react';
import NodeGroup from 'resonance/NodeGroup';

const colors = scaleOrdinal()
  .range([
    '#a6cee3',
    '#1f78b4',
    '#b2df8a',
    '#33a02c',
    '#fb9a99',
    '#e31a1c',
    '#fdbf6f',
    '#ff7f00',
    '#cab2d6',
    '#6a3d9a',
  ]);

// **************************************************
//  SVG Layout
// **************************************************
const view = [1000, 250];      // [width, height]
const trbl = [10, 10, 10, 10]; // [top, right, bottom, left] margins

const dims = [ // Adjusted dimensions [width, height]
  view[0] - trbl[1] - trbl[3],
  view[1] - trbl[0] - trbl[2],
];

// **************************************************
//  Mock Data
//  Data is being generated by Math.random in the
//  constructor and randomized in update
// **************************************************
const mockData = [
  {
    name: 'Linktype',
  }, {
    name: 'Quaxo',
  }, {
    name: 'Skynoodle',
  }, {
    name: 'Realmix',
  }, {
    name: 'Jetpulse',
  }, {
    name: 'Chatterbridge',
  }, {
    name: 'Riffpedia',
  }, {
    name: 'Layo',
  }, {
    name: 'Oyoba',
  }, {
    name: 'Ntags',
  },
];

const pieLayout = pie()
  .value((d) => d.value)
  .sort(null);

const arcPath = arc()
  .innerRadius((dims[1] / 3.5))
  .outerRadius((dims[1] / 2));

function arcTween(beg, end) {
  const i = interpolate(beg, end);

  return (t) => {
    return arcPath(i(t));
  };
}

class Example extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      arcs: this.getArcs(),
      arcsCache: {},
    };
  }

  getArcs = () => {
    const data = mockData.map(({ name }) => ({ name, value: Math.random() }));
    return pieLayout(data);
  }

  update = () => {
    this.setState((prevState) => ({
      arcs: this.getArcs(),
      arcsCache: prevState.arcs.reduce((m, n) => {
        return Object.assign(m, { [n.data.name]: n });
      }, {}),
    }));
  }

  render() {
    const { arcs, arcsCache } = this.state;

    return (
      <div>
        <button onClick={this.update}>
          Randomize
        </button>
        <Surface view={view} trbl={trbl}>
          <g transform={`translate(${dims[0] / 2}, ${dims[1] / 2})`}>
            <NodeGroup
              data={arcs}
              keyAccessor={(d) => d.data.name}

              start={(d) => ({
                fill: colors(d.data.name),
                d: arcPath(d),
                opacity: 0,
              })}

              enter={() => ({
                opacity: [1],
                timing: { duration: 1500 },
              })}

              update={(d) => ({
                opacity: [1],
                d: arcTween(arcsCache[d.data.name], d),
                timing: { duration: 1500 },
              })}

              leave={(d, index, remove) => {
                remove();
              }}

              render={(data, state) => {
                return (
                  <path {...state} />
                );
              }}
            />
          </g>

        </Surface>
      </div>
    );
  }
}

export default Example;