{
const width = 1000;
const height = 1000;
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width)
.attr("height", height);
const bg = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.attr("fill", "#121212");
const plot = svg
.append("rect")
.attr("x", 150)
.attr("y", 150)
.attr("width", 700)
.attr("height", 700)
.attr("fill", "none")
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.5");
for (let i = 250; i < 850; i = i + 100) {
const verticalPlotLines = svg
.append("line")
.attr("x1", i)
.attr("y1", 150)
.attr("x2", i)
.attr("y2", 850)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}
//plotting horizontal lines, ok
for (let i = 250; i < 850; i = i + 100) {
const horizontalPlotLines = svg
.append("line")
.attr("x1", 150)
.attr("y1", i)
.attr("x2", 850)
.attr("y2", i)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}
//text, nice: made it Korean
svg
.append("text")
.attr("x", width - 200)
.attr("y", height - 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("Korean-speaking population");
// nice: made it Dravidian
svg
.append("text")
.attr("x", 200)
.attr("y", 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("'Dravidian'-speaking population");
//creating a data source to use, ok
const censusData = [];
//cleaning data from the source and populating censusData, ok
for (let i = 1; i < languageData.length; i++) {
const state = languageData[i];
censusData.push({
name: state[0],
totalPopulation: parseInt(state[1]),
korean: state[3] == null ? 0 : parseInt(state[2]),
koreanPercent: state[3] == null ? 0 : parseInt(state[2]) / state[1],
dravidian: state[3] == null ? 0 : parseInt(state[3]),
dravidianPercent: state[3] == null ? 0 : parseInt(state[3]) / state[1],
fipsCode: state[4]
});
}
//extracting minimum and maximum numbers of korean and dravidian speaking populations, ok
const korMin = d3.min(censusData, (d) => d.korean);
const korMax = d3.max(censusData, (d) => d.korean);
const dvdMin = d3.min(censusData, (d) => d.dravidian);
const dvdMax = d3.max(censusData, (d) => d.dravidian);
//scaling values for korean and dravidian, hmm.......
const korScale = d3.scaleLinear().domain([korMin, korMax]).range([150, 850]);
const dvdScale = d3.scaleLinear().domain([dvdMin, dvdMax]).range([250, 850]);
//
const populationToParameter = d3
.scaleLinear()
.domain(d3.extent(censusData, (d) => d.dravidian))
.range([0, 1]);
//loop through data to populate scatter plot, ok
for (let i = 0; i < censusData.length; i++) {
//dvd on x-axis position
const xPosition = dvdScale(censusData[i].dravidian);
//kor on y-axis position and inverting the plot
const yPosition = height - korScale(censusData[i].korean);
//circles for each data point, ok
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", yPosition)
.attr("r", 8)
.attr(
"fill",
d3.interpolateViridis(populationToParameter(censusData[i].dravidian))
);
//text for each data point
svg
.append("text")
.attr("x", xPosition)
.attr("y", yPosition - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.style("fill", "white")
.text(censusData[i].name);
}
//show visualization in Observable
return svg.node();
}