The API

For this project, the best API I could find is the CoinDesk API. If you have a better bitcoin API, please tweet at me and let me know!

The CoinDesk API offers both real-time and historical bitcoin price data. For this project, I display the real-time bitcoin price in the top left corner (InfoBox.js). It updates every 90 seconds.

The historical price is what I use to provide data for the chart. The historical data endpoint is: https://api.coindesk.com/v1/bpi/historical/close.json

The API returns an object that looks like this:

{

“bpi”: {

“2017–06–24”: 2619.1188,

”2017–06–25": 2594.4538,

”2017–06–26": 2485.3588,

”2017–06–27": 2593.17,

”2017–06–28": 2584.5638,

// ...

}

}

Once I get the data back, I loop through it and format it into an array of objects:

for (let date in bitcoinData.bpi){

sortedData.push({

d: moment(date).format('MMM DD'),

p: bitcoinData.bpi[date].toLocaleString(),

x: count,

y: bitcoinData.bpi[date]

});

}

d : Formatted Date (ex: Jul 31)

: Formatted Date (ex: Jul 31) p : Formatted Currency String (ex: $2,000.46)

: Formatted Currency String (ex: $2,000.46) x : Count (numerical, beginning with 0)

: Count (numerical, beginning with 0) y : Unformatted Price (2000.46738 — used for graphing)

The data is then sent to a child component that builds the chart. Here’s a higher level overview of the data flow.

Basic Data Flow

The Data flow of the project is pretty straight forward:

app.js fetches historical data from the CoinDesk API and formats it into an array of objects. Data is passed to the LineChart.js component which renders the chart based on the data supplied from app.js . When the SVG component rendered in LineChart.js is hovered on, 3 things happen: LineChart.js draws a vertical line on the cursor coordinates. It determines the closest data point to the cursor and draws a circle to highlight that data point. Finally, data is passed back to app.js indicating the hover location, and closest point. app.js sends data to ToolTip.js so the tool tip can render in the correct location, and with the correct data. InfoBox.js runs independently of the other components and fetches real time data from the CoinDesk API every 90 seconds. The data is formatted and then displayed to the user.

Breaking Down the Graph

The Graph is not just one shape being drawn to the screen. It’s a collection of shapes and lines within a single SVG element. If you look at LineChart.js , you’ll see there are up to eight function calls used to create our graph:

this.makeAxis() Makes Graph Axis

this.makePath() Makes Graph Line

this.makeArea() Makes Shaded Graph Area (under line)

this.makeLabels() Makes Graph Labels this.getCoords(e) When Hovered Gets Coords of Hover

this.createLine() When Hovered Makes Vertical Line

this.makeActivePoint() When Hovered Finds Closest Point this.stopHover() Clears Line and Point When Hover Stops

Let’s look at an example. If we remove everything and only run makePath() we’re left with just an SVG line along our data points. Here’s what that looks like:

Just a path. Boring.

Likewise, we can remove everything except makeArea() and makeAxis() . This will draw our two Axis lines, and the shaded in shape. Here’s the result:

A little more interesting than above.

It isn’t until we start adding multiple shapes and lines together that our graph starts to look interesting. Withholding the hover effects, Here’s our graph with makeAxis() , makePath() , makeLabels() , and makeArea() :

Awesome!

The fun stuff happens when the SVG element is hovered over. On hover I run a function that gets the coordinates of the mouse on the graph. In order to do this we need two pieces of information:

The location of the SVG graph within the page The location of the mouse

Here’s what that code looks like:

I first get the svgLocation of the line chart within the page. Then, I adjust for any padding the chart may have. Finally I take the x location of the mouse and subtract the pixels that are to the left of the SVG chart. This gives me the location of the mouse relative to the line chart.

State is updated, and a vertical line is drawn on the graph at the mouse’s X coordinate:

Meanwhile, I can simply loop through the coordinates on our chart to determine which one has an X value closest to the mouse:

let {svgWidth} = this.props;

let closestPoint = {};

for(let i = 0, c = svgWidth; i < svgData.length; i++){

if ( Math.abs(svgData[i].svgX — this.state.hoverLoc) <= c ){

c = Math.abs(svgData[i].svgX — this.state.hoverLoc);

closestPoint = svgData[i];

}

}

Note: As Francesco Zuppichini pointed out in the comments, a binary search would be a better solution than simply looping through the array

After finding the closest X value, we draw an SVG circle at that point:

makeActivePoint(){

const {color, pointRadius} = this.props;

return (

<circle

className='linechart_point'

style={{stroke: color}}

r={pointRadius}

cx={this.state.activePoint.svgX}

cy={this.state.activePoint.svgY}

/>

);

}

The result is this:

The Tool Tip

The final part of the equation is the Tool Tip. The Tool tip is in a completely different component, but works just like our vertical line does. The Tool Tip needs two pieces of information to work:

The current mouse location The closest data point

Both of these pieces of information are received from LineChart.js . ToolTip.js then simply returns a <div> element centered above the mouse. with the formatted data from the closest data point.

let placementStyles = {};

let width = 100;

placementStyles.width = width + 'px';

placementStyles.left = hoverLoc + svgLocation.left - (width/2); return (

<div className='hover' style={ placementStyles }>

<div className='date'>{ activePoint.d }</div>

<div className='price'>{activePoint.p }</div>

</div

)

...

Where’s the code?

Glad you asked. All the code for this project is open source and available in my GitHub Repo. The live demo, once again, is here.

If the SVG elements of this project interest you, I go into more detail on the graph in my previous article: Simple Data Visualization with React JS. If you really want to dive into React and learn how to build cool things, check out my 3 Best React JS Courses.

If this post was helpful, please click the clap 👏button below a few times to show your support! ⬇⬇

I publish a few articles and tutorials each week, please consider entering your email here if you’d like to be added to my once-weekly email list.