-
Notifications
You must be signed in to change notification settings - Fork 0
D3js
D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
Table of Contents
The first thing that needs to be done when visualizing data is getting the data.
d3-fetch provides utility methods that will fetch data from a file and parses it into a Javascript Object.
d3-fetch is able to parse different file formats. including .json and .csv files.
I ran into some problems when fetching the data from the .csv, after some research I found out that I had to specify the delimiter.
To fetch the .csv data with ; as a delimiter i used the next function.
dsv(';', url, autoType, cleanParkingData).then(setData);autoType is a function from d3 that transforms the type of values from the objects and makes them usable.
cleanParkingData is a function I wrote to transform and edit some values for rendering to the DOM
const cleanParkingData = (d) => {
cleanProvince(d);
cleanUsage(d);
d.id = +d.id;
d.minimumHeightInMeters = +d.minimumHeightInMeters;
d.latitude = +d.latitude;
d.longitude = +d.longitude;
d.capacity = +d.capacity;
return d;
};This functions replaces a value from d.province if there is one
const cleanProvince = (d) => {
if (!d.province) return;
d.province = d.province.replace('Fryslân', 'Friesland');
return d;
};This Functions replaces the d.usage values with values I want to render to the dom
const cleanUsage = (d) => {
try {
d.usage = d.usage
.replace('park and ride', 'P+R Parkeerplaats')
.replace('garage', 'Parkeergarage')
.replace('terrain', 'Parkeerterrein');
return d;
} catch (error) {
console.error(error);
}
return d;
};After manipulating and cleaning the data. I wanted the results to be formatted and reduced.
Function:
export const formatData = (data) => {
return data.map((d) => {
return {
id: d.id,
name: d.name,
province: d.province,
usage: d.usage,
city: d.city,
latitude: d.latitude,
longitude: d.longitude,
capacity: d.capacity,
minHeign: d.minimumHeightInMeters,
};
});
};The map function I wrote produces a new array with only the values I need.
Input:
{
"id": 1,
"name": "P+R Station Appingedam (Appingedam)",
"staticDataUrl": "https://npropendata.rdw.nl//parkingdata/v2/static/fc749565-1fe9-42f0-920a-3b4e718d62f9",
"dynamicDataUrl": "",
"limitedAccess": "0",
"uuid": "fc749565-1fe9-42f0-920a-3b4e718d62f9",
"latitude": 53.325488634795,
"longitude": 6.8620881539554,
"city": "Appingedam",
"country_code": "nl",
"province": "Groningen",
"region": "Noord-Nederland",
"mark": "good",
"usage": "P+R Parkeerplaats",
"accessPoints": "1",
"capacity": 22,
"contactPersons": "1",
"minimumHeightInMeters": 0,
"openingTimes": "1",
"tariffs": "1",
"Operator": "Appingedam"
},
{
...
}Output:
{
"id": 1,
"name": "P+R Station Appingedam (Appingedam)",
"province": "Groningen",
"usage": "P+R Parkeerplaats",
"city": "Appingedam",
"latitude": 53.325488634795,
"longitude": 6.8620881539554,
"capacity": 22,
"minHeign": 0
},{
...
}To create a pie chart I had to manipulate and nest values. To do this I used the rollups function from d3. This function returns a nested array.
Function:
export const nestedData = (data) => {
const nested = rollups(
data,
(v) => v.length,
(d) => d.usage
);
return nested;
};Input:
{
"id": 1,
"name": "P+R Station Appingedam (Appingedam)",
"province": "Groningen",
"usage": "P+R Parkeerplaats",
"city": "Appingedam",
"latitude": 53.325488634795,
"longitude": 6.8620881539554,
"capacity": 22,
"minHeign": 0
},{
...
}Output:
[
['P+R Parkeerplaats', 329],
['Parkeergarage', 540],
['Parkeerterrein', 114],
];d3-selection has alternative methods to document.querySelector() and is called d3.select()
This method creates a d3 selection object with helper methods that can be used to manipulate the dom.
select('g.pie') selects the first g element that has the classname .pie.
const selection = select('g.pie');selectAll('g.arc') selects all g.arc elements that will be rendered to the dom and .data(pieData) binds data to these elements.
const selectionWithData = selection.selectAll('g.arc').data(pieData);These d3 methods will remove elements from the DOM if the associated data to that element is changed or removed.
selectionWithData.exit().remove();selection.enter() gets enter selection of data with missing elements.
selection.append('g') creates dom elements for each data point without a DOM element
const selectionWidthUpdate = selectionWithData
.enter()
.append('g')
.attr('class', 'arc');returns a new selection merging this selectionWidthUpdate with the specified other selection.
In this case
selectionWidthUpdate() is merged with selectionWithData.select('path.arc')
const path = selectionWidthUpdate
.append('path')
.merge(selectionWithData.select('path.arc'));