#1.  Building Color Wheel 🎯 visualisation  (visx cookbook 📚)
Tags: visx, react, d3, dataviz
Published: 2021-05-10 23:11:22

## Hi 👋
Welcome to the data visualization cookbook here you will learn how to play with primitive SVG shapes and d3 functions to build magical visualizations.

### Our new start Visx 🌟
[Visx](https://airbnb.io/visx/) Airbnb is a collection of expressive, low-level visualization primitives for React built on top of the famous D3 library, Visx provide us with the fundamentals pieces that we need to build our data visualization, and our library their goal is to empower devs to build their data visualization component libraries.

## Why I built this series 🧐 ?
I was working with d3 inside of react to build some custom charts and DataViz for my client and having the shittest experience ever trying to combine d3 and react together, and like that, I stumbled into VISX my savior this library it's all that I wanted it gave me freedom and power of d3 while keeping my boy react in charge of the dom, one problem I found with Visx there is not enough documentation and examples especially for people that don't master d3 so I took it upon my self to change this fact and create this series of 20 recipes to teach people how to use this amazing tool also while building a data viz library with 19 components, follow along with reader at the end of this series you will have learned Visx, some new charts and built a react visualization library 🥏. 

![Visualizing-Meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbc4rnb50eoau2rj0vld.jpg)

##Go! 

## #1. Building Color Wheel 🎯

{% codesandbox color-wheel-pie-arc-rrfyc %} 

In this first recipe we are going to build a Color Wheel it's simple and beginner-friendly and at the same time will help us get a good grasp of Visx and its capabilities.

This piece will be useful to those starting with Visx. We’ll be looking over methods for creating and manipulating color, with examples included. Note that no prior knowledge of **Visx** is required to follow this article.

###Key visx ingredient of our recipe 🗝️ : 

* [**Arc**](https://airbnb.io/visx/docs/shape#Arc) 

* [**Pie**](https://airbnb.io/visx/docs/shape#Pie)

* [**Group**](https://airbnb.io/visx/docs/group)

* [**ParentSize**](https://airbnb.io/visx/docs/responsive#ParentSize)

### 1. Prepare Data
To visualize data, we'll want to represent data points as shapes. so to start we need to look at our data first our data is a multidimensional array each array represents colors of the rainbow at a certain brightness, so to build our color wheel all we need to do is to map each array to a pie of arcs and like that we will have a wheel of multiple pies.


```js
const data = [
// a pie  
[
    'rgb(76, 110, 219)', // a single arc
    'rgb(110, 64, 170)',
    'rgb(191, 60, 175)',
    'rgb(254, 75, 131)',
    'rgb(255, 120, 71)',
    'rgb(226, 183, 47)',
    'rgb(175, 240, 91)',
    'rgb(82, 246, 103)',
    'rgb(29, 223, 163)',
    'rgb(35, 171, 216)'
  ],
// 2 nd pie 
 [
    'rgb(76, 110, 219)', // a single arc
    'rgb(110, 64, 170)',
    'rgb(191, 60, 175)',
    ...
  ],
	.....
];
```
*color wheel data visualization data structure /data.js* 


### 2. Build a Color Grid

Let's first build something easy to give is a better idea of our data, we are going to build a color matrix each row represents an array of our matrix and each rectangle represents a single data point with its color as that data point value.

{% codesandbox color-table-dos29 %}


```jsx
import React from "react";
import { colorMatrix } from "./data";
import { color as d3Color } from "d3-color";

const convertRgbToHex = (rgb) => d3Color(rgb).formatHex();

export default function Example({ width, height }) {
  return width < 10 ? null : (
    <div className="chords">
      <svg width={width} height={height}>
        {colorMatrix.map((arr, id) => {
          return arr.map((color, key) => {
            return (
              <>
                <rect
                  fill={color}
                  width={width / 8}
                  x={(width / 8) * key}
                  y={50 * id}
                  height={"50"}
                ></rect>
                <text y={50 * id} fill="white" x={(width / 8) * key}>
                  {convertRgbToHex(color)}
                </text>
              </>
            );
          });
        })}
      </svg>
    </div>
  );
}
```

Here the code is very straightforward we are iterating over the matrix and then iterating on the individual array to build rectangles all we are manipulating is using the index to change the position of the rectangles, quite easy isn't it, I think with this we are pretty sure we understand our data structure, let's map this idea to the color wheel in the color wheel each array represents a single pie and each data point (color) represents an arc of that pie,
An Arc is a primitive shape of the Visx shapes module "@visx/shape" it's built on D3 arc shape, this arc component can build us an arc path using D3 magic.

### 3. Build Arcs

{% codesandbox visx-arc-example-5bwft %}


We can see here we can use an arc component by itself without any data and the props are pretty easy to understand bounding angles, pad between arcs, the radius of the arc corners and by the way, the arc also takes any SVG props like (fill, opacity, ....)

```jsx
import React from "react";
import { Arc } from "@visx/shape";
import { Group } from "@visx/group";

export default function Example({ width, height }) {
  return width < 10 ? null : (
    <div className="chords">
      <svg width={width} height={height}>
        <Group top={height / 2} left={width / 2}>
          <Arc
            startAngle={0}
            endAngle={2}
            outerRadius={20}
            innerRadius={150}
            padAngle={0.1}
            cornerRadius={3}
            fill={"#F28F38"}
          />
          <Arc
            startAngle={2}
            endAngle={6.3}
            outerRadius={20}
            innerRadius={150}
            padAngle={0}
            cornerRadius={3}
            fill={"#F25757"}
            opacity={1}
          />
        </Group>
      </svg>
    </div>
  );
}
```

In our color wheel, our arcs had text in the middle of them representing the colors in HEX we need to create a custom arc component to have that capability, Visx provides a pretty reactive way of overriding the arc render using "React Render prop pattern" basically Vsix pass all the SVG path generated by d3.arc function to the children component of **<Arc/>** component as we can see here from source code. 

```jsx
const path = arc({
    innerRadius,
    outerRadius,
    cornerRadius,
    startAngle,
    endAngle,
    padAngle,
    padRadius,
  });

  // eslint-disable-next-line react/jsx-no-useless-fragment
  if (children) return <>{children({ path })}</>;
```

Build custom arc with text (render props)

```jsx
const CustomArc = ({ path, color }) => {
  return (
    <>
      <path d={path()} fill={color} />
      <text
        fill="white"
        x={path.centroid(path)[0]}
        y={path.centroid(path)[1]}
        dy=".33em"
        fontSize={8}
        textAnchor="middle"
        pointerEvents="none"
      >
        {color}
      </text>
    </>
  );
};
```

To build our custom arc we use the path function we pass it to the path SVG element and we pass our color value to the text element we use the **path.centroid** to center our text on top of the arc

we use our custom arc like this : 

```jsx
<Arc
    startAngle={5}
    endAngle={6.3}
    outerRadius={20}
    innerRadius={150}
    padAngle={0.1}
    cornerRadius={3}
    fill={"#F25757"}
    opacity={1}
    >
    {({ path }) => <CustomArc color={"#F56754"} path={path} />}
</Arc>
```

Now we learned how to build an arc next is how to build a pie with arcs?

### 4. Build a Pie

Pie is a primitive shape of the Visx shapes module "@visx/shape" it's built on top of d3.pie shape, this pie component generates Arcs shapes data based on provided data prop 

So in this example, we can see that the pie component take as prop data as an array that data will be used to create arcs and the size of the arcs will follow the data in the array 

{% codesandbox pie-example-bwkjv %}

```jsx
<Pie
  data={[1, 1, 2, 3, 5, 8, 13, 21]}
  cornerRadius={3}
  padAngle={0.005}
  >
  {(pie) => <PieArc {...pie} radius={radius} pieNumber={0} />}
</Pie>
```

```jsx
const PieArc = ({ arcs, radius, pieNumber }) => {
  return arcs.map(({ startAngle, endAngle }, key) => {
    return (
      <Arc
        key={key}
        startAngle={startAngle}
        endAngle={endAngle}
        outerRadius={(radius * (pieNumber + 1)) / 3 - PIES_SPACING}
        innerRadius={radius * (pieNumber / 3)}
        fill={COLORS[pieNumber + 1]}
        padAngle={ARCS_SPACING}
        cornerRadius={5}
      />
    );
  });
};
```

We can also pass a prop **"pieValue"** that can be used as an accessor if the array contains objects we can pass a function to **"pieValue"** to select the value that we need for example if we have an array with
```
 [{name : 'beta', value:2}, {name : 'beta', value:5}] 
```
we will need to pass this prop to Pie component 

```jsx
pieValue={(d) => d.value}
```

If we want to ignore the values inside of the data prop and have all the arcs of the same size we need to pass this prop to the component

```jsx
pieValue={(d) => 1}
```

### 5. Let's build our color Wheel

Now we have all the ingredients for our main dish the color wheel let's now stir them up.

We start by creating our main component that will call the color wheel and will add to it "ParentSize" component from "@visx/responsive" module to make sure that our data visualization will be responsive.
     
```jsx
import React from "react";
import { render } from "react-dom";
import { ParentSize } from "@visx/responsive";
import ColorWheel from "./ColorWheel";
import "./sandbox-styles.css";

render(
  <ParentSize>
    {({ width, height }) => <ColorWheel width={width} height={height} />}
  </ParentSize>,
   document.getElementById("root")
  );
```

Now let's create our main component the colorWheel
    1. Our main component takes ** height, width** as props and use is to calculate the radius of the wheel
    2. We are using the <**Group/>** Visx component to wrap the components in a **<g/>** SVG element
    3. Our data is a multidimensional array with each array containing colors of a single pie, we iterate over them and we pass each array of color to a **<Pie/>**  component also we are providing an accessor prop pieValue to make sure all created arcs will have the same size
    4. We pass the generated data to our custom Arcs component <ColorPie/> and also we pass the length and the radius of the pies also the **pieNumber** (index of the current pie) to calculate the with and radiuses of each pie.

```jsx
export function ColorWheel({ width, height }) {
  const radius = Math.min(width, height) / 2;

  return (
    <div>
      <svg width={width} height={height}>
        <rect width={width} height={height} fill={BACKGROUND_COLOR} rx={14} />
        <Group top={height / 2} left={width / 2}>
          {colorMatrix.map((el, key) => (
            <g key={`wheels-${key}`}>
              <Pie
                key={key}
                data={colorMatrix[key]}
                cornerRadius={3}
                padAngle={0.005}
                pieValue={d => 1}
              >
                {pie => {
                  return (
                    <ColorPie
                      {...pie}
                      pieRadius={radius}
                      currentPieNumber={key}
                      numberOfPies={colorMatrix.length}
                    />
                  );
                }}
              </Pie>
            </g>
          ))}
        </Group>
      </svg>
    </div>
  );
}
```


We build the <ColorPie/> component that will be responsible for passing the arcs data to the custom arcs to build each Pie
    1. here we are passing a constant arc spacing to separate the arcs.
    2. we are using the utility functions to calculate the arcs outer and inner radius, cause by default the pie generate arcs that will build a full pie but here we need rings so for that we need to calculate each arc outer and inner radius.

```js
const getArcOuterRadius = ({ pieRadius, numberOfPies, currentPieNumber }) =>
          (pieRadius * (currentPieNumber + 1)) / numberOfPies - PIE_SPACING;

const getArcInnerRadius = ({ pieRadius, numberOfPies, currentPieNumber }) =>
          pieRadius * (currentPieNumber / numberOfPies)
```

```js
const ColorPieArc = props => {
  const { arcs, pieRadius, currentPieNumber, numberOfPies } = props;
  return arcs.map(({ startAngle, endAngle, data }, key) => {
    return (
      <Arc
        key={key}
        startAngle={startAngle}
        endAngle={endAngle}
        outerRadius={getArcOuterRadius({
          pieRadius,
          numberOfPies,
          currentPieNumber
        })}
        innerRadius={getArcInnerRadius({
          pieRadius,
          numberOfPies,
          currentPieNumber
        })}
        padAngle={ARCS_SPACING}
        cornerRadius={5}
      >
        {({ path }) => (
          <CustomArc
            color={data}
            path={path}
            i={key}
            opacity={1}
            currentPieNumber={currentPieNumber}
          />
        )}
      </Arc>
    );
  });
};

```

      

The last step is to build our <CustomArc/> as we did before

```jsx
const CustomArc = ({ path, color }) => {
  return (
    <>
      <path d={path()} fill={color} />
      <text
        fill="white"
        x={path.centroid(path)[0]}
        y={path.centroid(path)[1]}
        dy=".33em"
        fontSize={8}
        textAnchor="middle"
        pointerEvents="none"
      >
        {convertRgbToHex(color)}
      </text>
    </>
  );
};
```

Here it's the same component we built before the difference here is that our data is in RGB so we used a function **convertRgbToHex** to convert RGB to hex.

```jsx
const convertRgbToHex = (rgb) => d3Color(rgb).formatHex();
```

### Bonus :

Generate color wheel data : 

Creating the color data is a fun way to learn some d3 color techniques, here we are using *interpolateRainbow* a function that when we provide it with a number from 0 to 1 it gives an RGB color from the rainbow so what we do is iterate over the pies and we use *visx/scale* to get the map for the index of the element to a number between 0 and 1.


```jsx
import { scaleLinear } from "@visx/scale";
import { _arrayOf } from "./utils";
import { interpolateRainbow } from "d3-scale-chromatic";

const numberOfArcs = 10;
const numberOfPies = 8;
let pies = _arrayOf(numberOfPies, []);

for (let i = 0; i < numberOfArcs; i++) {
  let scale = scaleLinear({
    domain: [0, numberOfPies],
    range: [(i - 1) / numberOfArcs, i / numberOfArcs]
  });
  pies = pies.map((d, i) => {
    return [...d, interpolateRainbow(scale(i))];
  });
}
export const colorMatrix = pies;
```

### Some Variation :

**#1** Color wheel without using the pie component

{% codesandbox color-wheel-cpxpz %}


**#2** Color wheel with native SVG elements and react-spring animation

{% codesandbox color-wheel-v2-12ke3 %}