// https://bl.ocks.org/sebg/6f7f1dd55e0c52ce5ee0dac2b2769f4b let margin = {top: 100, right: 20, bottom: 100, left: 150}, width = 1200 - margin.left - margin.right, height = 700 - margin.top - margin.bottom; let axisTitleFontStyle = "16px sans-serif"; let plotTitleFontStyle = "20px sans-serif"; let x_axis_attr = "age"; let y_axis_attr = "worth in billions"; let color_dot_attr = "category"; let x_axis_title = titleCase(x_axis_attr); let y_axis_title = titleCase(y_axis_attr); let color_dot_title = titleCase(color_dot_attr); let svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // read data and draw d3.csv("billionaires.csv", function(error, data) { if (error) throw error; data = data.filter(d => +d[x_axis_attr] !== -1); data.forEach(function(d) { d[x_axis_attr] = +d[x_axis_attr]; d[y_axis_attr] = +d[y_axis_attr]; }); let x = d3.scaleLinear() .domain(d3.extent(data, function(d) { return d[x_axis_attr];})) .range([0, width]); let y = d3.scaleLinear() .domain(d3.extent(data, function(d) { return d[y_axis_attr];})) .range([height, 0]); let color = d3.scaleOrdinal(d3.schemeCategory10); let xAxis = d3.axisBottom().scale(x); let yAxis = d3.axisLeft().scale(y); // x axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "1em") .attr("dy", "1em"); // y axis svg.append("g") .attr("class", "y axis") .call(yAxis); // x axis title svg.append("text") .style("font", axisTitleFontStyle) .attr("text-anchor", "middle") .attr("transform", "translate("+ (width/2) +","+(height+(margin.bottom-(margin.bottom/7)))+")") .text(x_axis_title); // y axis title svg.append("text") .style("font", axisTitleFontStyle) .attr("text-anchor", "middle") .attr("transform", "translate("+ (0-margin.left/2) +","+(height/2)+")rotate(-90)") .text(y_axis_title); // main title svg.append("text") .style("font", plotTitleFontStyle) .attr("text-anchor", "middle") .attr("transform", "translate("+ (width/2) +","+(-margin.top/2)+")") .text(x_axis_title + " v.s. " + y_axis_title + " v.s. " + color_dot_title); // draw plot svg.selectAll(".dot") .data(data) .enter() .append("circle") .attr("class", "dot") .attr("r", 3.5) .attr("cx", function(d) { return x(d[x_axis_attr]); }) .attr("cy", function(d) { return y(d[y_axis_attr]); }) .style("fill", function(d) { return color(d[color_dot_attr]); }); // legend let legend = svg.selectAll(".legend") .data(color.domain()) .enter() .append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width - 12) .attr("width", 12) .attr("height", 12) .style("fill", color); legend.append("text") .attr("x", width - 16) .attr("y", 5) .attr("dy", ".35em") .style("font", axisTitleFontStyle) .style("text-anchor", "end") .text(function(d) { if(d === ""){ return "\"\"";} return d;}); }); function titleCase(str) { str = str.toLowerCase().split(' '); for (var i = 0; i < str.length; i++) { str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1); } return str.join(' '); }