Electron Adventures: Episode 6: Use D3 To Visualize Free Disk Space
In previous episode we created a small app that displays how much free disk space you have, in a very boring way.
Now it's time to spice it up! We won't touch the backend at all, and only modify the frontend.
Install D3
First we need to install D3.
$ npm install d3
Do not use CDN version. This will stop your app working offline, and even worse, it introduces potential security risk. It's possible to use CDNs safely, but Electron security already is much harder than web app security, so let's not overcomplicate things.
Most frontend apps these days use bundlers like rollup or webpack, but for now let's just include it as regular browser javascript.
So here's the frontend HTML code. I added some styling in advance:
<!DOCTYPE html>
<html>
<body>
<style>
body { text-align: center; }
#info { display: grid; grid-template-columns: 1fr 1fr 1fr; }
</style>
<h1>Free disk space</h1>
<div id="info"></div>
<script src="./node_modules/d3/dist/d3.js"></script>
<script src="app.js"></script>
</body>
</html>
A lot of frontend Javascript packages, even if they recommend using bundlers, have something you can include under node_modules/packagename/dist/packagename.js
.
D3 app
And here's the D3 app. I won't explain it in too much detail, as D3 is a big subject, and it's only incidental to what we're doing here.
We get data
from the backend thought displayFreeDiskSpace
callback, then we loop it for each disk, and create div
with an h3
header and a svg
pie chart. Most of the complicated code is pie chart creation, and we use a lot of D3 helpers for it.
function displayFreeDiskSpace(data) {
let info = d3.select("#info")
for (let row of data) {
let total = parseInt(row[1])
let used = parseInt(row[2])
let free = total - used
let path = row[5]
let data = { free, used }
let div = info.append("div")
div.append("h3").text(path)
let svg = div
.append("svg")
.attr("width", "100px")
.attr("height", "100px")
let g = svg
.append("g")
.attr("transform", "translate(50,50)")
let pie = d3.pie().value(d => d[1])
let pieData = pie(Object.entries(data))
let color = d3
.scaleOrdinal()
.domain(["used", "free"])
.range(["red", "green"])
g
.selectAll("path")
.data(pieData)
.enter()
.append("path")
.attr("d", d3.arc()
.innerRadius(0)
.outerRadius(45)
)
.attr("fill", d => color(d.data[0]))
.attr("stroke", "black")
.style("stroke-width", "2px")
.style("opacity", 0.7)
}
}
Result
All the code for the episode is here.
In the next episode we'll have a fun little detour.