The post today is about making a dynamic bar chart with random auto-generated data. React with hooks and the use of SVG make this application easier to make and cleaner in code. We simply just need a component for a single bar and another index file of the application. And I also add some css animation that makes the bar chart animate nicely.

Click “Generate” to generate new data

What is SVG

Basically, <svg> is a tag in HTML that helps you make draw vector graphic in the browser. And vector graphic won’t be pixelated no matter how much pixel your screen is or while being zoomed in.

Inside <svg> tag, you can draw any shape you want, and in this post, we just need to draw a rectangle which is easy. I will use <path> tag, to draw the line into a rectangle.

The most important attribute of <path> tag is “d”. This d attribute will define the way that the line will be stroked. See the example below:

<path d="M 0 300 L 0  30 L 60 30 l 60 300 Z" />

I had a painful time to realize that the info for “d” is case sensitive, so don’t write it in lowercase. After the character is 2 numbers represent for X and Y of the point.

  • M: starting point
  • L: The next point that the line should go to
  • Z: tell the line to come back to the starting point

First, make a single bar

import React from "react";
import ReactDOM from "react-dom";

function SingleBar({ width, height, data, color, percentage }) {
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center"
}}
>
<svg style={{ marginLeft: 5 }} width={width} height={height}>
<path
style={{
animation: "bounce linear 400ms",
transformOrigin: "50% 100%",
margin: "auto"
}}
d={data}
fill={color}
/>
</svg>
<p style={{ fontSize: 12 }}>{percentage}</p>
</div>
);
}

export default SingleBar;

  • This SingleBar component will accept 5 parameters:
  • width and height: for defining the size of drawable svg area.
  • data: information for drawing the bar inside svg area.
  • color: you know it, for fill the color of the bar
  • percentage: display the percentage number below the bar (just a fancy stuff)

Sencond, App index

After having the SingleBar component, now it’s time to make use of it. With the sake of react hooks, I don’t need to use a class component to manage the state of the app.

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

import SingleBar from "./components/SingleBar";

const max = 300;

function App() {
const [list, setList] = useState([]);

useEffect(() => {
genList();
}, []);

const genList = () => {
const list = [];
for (let i = 0; i < 5; i++) {
list[i] = Math.random() * 101;
}
setList(list);
};
return (
<div>
<div style={{ display: "flex" }}>
{list.map(e => {
const y = max - (max * e) / 100;
return (
<SingleBar
key={e}
width="60px"
height="300px"
color="#ea1"
percentage={`${Number(e).toFixed(2)} %`}
data={`M 0 ${max} L 0 ${y} L 60 ${y} l 60 ${max} Z`}
/>
);
})}
</div>
<button onClick={genList}>Generate</button>
</div>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

const [list, setList] = useState([]): make a list which is an array initialized to be empty, setList is a method that will be used to update the list.

genList() method is used for making an array of 5 elements with random values from 0 – 100 which is a percentage. This array will then be used to update into the state of list.

useEffect: works similar to componentDidMount method, since I want to generate the new list when the application starts. The send parameter of useEffect, in this case, is significant since it declares what to be subscribed to rerender. I put an empty [] as I don’t want anything to be watched. If you don’t provide this, the application will be rerendered constantly as the state is changed every time the useEffect is called after the application mounted.

The return() method return what will be display in the screen, basically, just map through the whole list and with each elements, it will calculate the hight of the bar and render the SingleBar component with the particular value.

Animation for the Bar

@keyframes bounce {
0% {
transform: scale(0);
}

80% {
transform: scale(1.1);
}

100% {
transform: scale(1);
}
}

I use key frame to define the animation for the bar, so it won’t be display immediately in a boring way. Every bar will be scale up from 0 t 1.1 then scale down to the actual size (1) at the end of the animation.

LEAVE A REPLY

Please enter your comment!
Please enter your name here