Today we add to Codernews to provide more content to our users.
We need a new page specifically for the cryptocurrencies prices chart.
Start by implementing a way to navigate to this new page from the homepage.
<li class="nav-item">
<a class="nav-link" href="crypto.html">Crypto</a>
</li>
crypto.html
.Negative : When we navigate to crypto.html
we see that all the html we wrote in index.html
is lost...
index.html
into crypto.html
.Negative : Copying everything from index.html
into crypto.html
works but introduces the problem of a substantial amount of code duplication.
We want this page to only show Crypto so we'll remove some code while adding different code.
This open source code will help us tremendously in this project.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
Positive : It's using Canvas internally. We know that!
scripts.js
from crypto.html
.Remove scripts.js
because we won't render news to the U.I. on this screen
<script src="js/scripts.js"></script>
<div class="col text-center">
<h1 id="title" class="mt-5 title">CoderNews</h1>
<ul id="newsList" class="list-group"></ul>
</div>
crypto.js
.crypto.html
.<script src="crypto.js"></script>
<canvas id="myChart" width="600" height="400"></canvas>
Let's add the logic to fetching crypto data & rendering the chart into crypto.js
.
cryptoURL
that gives us data on cryptocurrencies.Make sure to replace YOUR_API_KEY
with the one you got from the site.
const cryptoURL =
"https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?start=1&limit=3&convert=USD&CMC_PRO_API_KEY=YOUR_API_KEY";
getCryptoPrices()
.We call an api and parse it's response.
async function getCryptoPrices() {
const response = await fetch(cryptoURL);
const json = await response.json();
const coin = json.data[0];
console.log(coin);
}
getCryptoPrices()
after it's defined.getCryptoPrices();
const coin = {
id: 1,
name: "Bitcoin",
symbol: "BTC",
slug: "bitcoin",
num_market_pairs: 9852,
date_added: "2013-04-28T00:00:00.000Z",
tags: [
"mineable",
"pow",
"sha-256",
"store-of-value",
"state-channels",
"coinbase-ventures-portfolio",
"three-arrows-capital-portfolio",
"polychain-capital-portfolio",
],
max_supply: 21000000,
circulating_supply: 18651531,
total_supply: 18651531,
platform: null,
cmc_rank: 1,
last_updated: "2021-03-12T07:22:02.000Z",
quote: {
USD: {
price: 56772.22509134523,
volume_24h: 56146078171.69906,
percent_change_1h: 0.45440337,
percent_change_24h: 2.1565927,
percent_change_7d: 20.01380942,
percent_change_30d: 22.3897859,
percent_change_60d: 67.00783825,
percent_change_90d: 209.20232707,
market_cap: 1058888916230.2034,
last_updated: "2021-03-12T07:22:02.000Z",
},
},
};
Positive : All APIs are called following the same pattern, Async/Await & Fetch/URL/.json().
Time to use the data with ChartJS.
renderLineGraph()
which will render our chart to the screen.Notice we call it after we get our data and we pass it an single coin.
async function getCryptoPrices() {
const response = await fetch(cryptoURL);
const json = await response.json();
const coin = json.data[0];
renderLineGraph(coin);
}
renderLineGraph()
Here we select the canvas
then use new Chart
and ctx
to draw to it.
We also pass it data using a helper function, getHistoricPrices()
, which requires a single coins price as an argument.
function renderLineGraph(coin) {
const ctx = document.getElementById("myChart");
const price = coin.quote.USD.price;
const [ninetyAgoPrice] = getHistoricPrices(coin.quote.USD);
const timeAgo = ["90d", "60d", "30d", "7d", "24h", "1h", "Current"];
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: timeAgo,
datasets: [
{
label: "Price",
borderWidth: 1,
data: getHistoricPrices(coin.quote.USD),
borderColor: "rgba(255, 99, 132, 1)",
backgroundColor: "rgba(255, 99, 132, 0.2)",
},
],
},
options: {
tooltips: {
enabled: true,
mode: "nearest",
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: false,
suggestedMax: price,
suggestedMin: ninetyAgoPrice,
},
},
],
},
},
});
}
getHistoricPrices()
which accepts a prices object and returns an array of prices.calculatePriceFromPercentageChange()
, which looks at the current price and the percentage of change from current price to determine the coins price at that point in time.function getHistoricPrices(prices) {
const {
percent_change_90d,
percent_change_60d,
percent_change_30d,
percent_change_7d,
percent_change_24h,
percent_change_1h,
price,
} = prices;
const ninetyAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_90d
);
const sixtyAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_60d
);
const thirtyAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_30d
);
const sevenAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_7d
);
const dayAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_24h
);
const hourAgoPrice = calculatePriceFromPercentageChange(
price,
percent_change_1h
);
return [
ninetyAgoPrice,
sixtyAgoPrice,
thirtyAgoPrice,
sevenAgoPrice,
dayAgoPrice,
hourAgoPrice,
price,
];
}
calculatePriceFromPercentageChange()
which calculates the price of the coin given the percentage diff and current price.Unfortunately the data isn't structured how we want it so we need to perform these computations ourselves.
function calculatePriceFromPercentageChange(currentPrice, percentageChange) {
let denominator;
let historicPrice;
if (percentageChange >= 100) {
percentageChange = percentageChange + 100;
denominator = percentageChange * 0.01;
historicPrice = currentPrice / denominator;
}
if (percentageChange < 100 && percentageChange > 0) {
denominator = 1 + percentageChange / 100;
historicPrice = currentPrice / denominator;
}
if (percentageChange < 0) {
const original = (currentPrice / (100 + percentageChange)) * 100;
historicPrice = original;
}
return historicPrice;
}
getHistoricPrices()
and pass it's return value to datasets[0].data
.getHistoricPrices()
the coin's prices.var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["90d", "60d", "30d", "7d", "24h", "1h", "Current"],
datasets: [
{
label: "Price",
borderWidth: 1,
borderColor: "rgba(255, 99, 132, 1)",
data: getHistoricPrices(coin.quote.USD),
backgroundColor: "rgba(255, 99, 132, 0.2)",
},
],
},
});
Your technical lead did the heavy lifting for you. See if you can build on the shoulders of giants.