Published
Edited
Apr 17, 2019
Fork of Scatter plot
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
//tooltip option with d3-tip
/*
const tooltip = d3tip()
.style("font-family", "Helvetica")
.style("text-anchor", "left")
.style("font-size", "16px")
.style("border", "solid 1px rgba(0, 0, 0, 0.4)")
.style("border-radius", "5px")
.style("padding", "10px")
.style("background-color", "white")
.style("float", "left")
.html(d => `
<div>
Country: ${d.countries} </br>
Personal Freedom Score: ${decFormat(d.pf_score)} </br>
Population: ${bigFormat(d.population)} </br>
GDP per capita: ${bigFormat(d.gdp_ppp_cap)}
</div>`);
svg.call(tooltip);
*/
//bubbles
svg.append("g")
.selectAll("g")
.data(freedom_2016)
.join("circle")
.attr("id", (d, i) => "point-" + i)
.attr("cx", d => xScale(d.population))
.attr("cy", d => yScale(d.gdp_ppp_cap))
.attr("r", d => aScale(d.pf_score))
.attr("fill-opacity", 0.5)
.attr("fill", d => colorScale(d.region))
let limVoronoi = d3.distanceLimitedVoronoi()
.x(d => xScale(d.population))
.y(d => yScale(d.gdp_ppp_cap))
.limit(25)
//.clipExtent([0, 0], [width, height]); //this wasn't working weirdly
svg.append("g")
.selectAll("path")
.data(limVoronoi(freedom_2016))
.enter().append("path")
.attr("d", (d, i) => { console.log("d is:", d); return d.path})
//.datum((d, i) => d.point)
.attr("id", (d, i) => "voronoi-" + i)
.style("stroke", "steelblue")
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", tooltipMouseOver)
.on("mouseout", tooltipMouseOut)
//x axis
svg.append("g")
.call(xAxis);
//y axis
svg.append("g")
.call(yAxis);
//x grid lines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.attr("stroke-opacity", 0.1)
.call(make_x_gridlines()
.tickSize(-height+margin.top+margin.bottom)
.tickFormat("")
)
//y grid lines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(" + margin.left + ",0)")
.attr("stroke-opacity", 0.1)
.call(make_y_gridlines()
.tickSize(-width + margin.left + margin.right)
.tickFormat("")
)
//x axis label
svg.append("text")
.attr("class", "text")
.attr("transform", "translate(" + (width/2) + "," + (height - 20) + ")")
.style("text-anchor", "middle")
.style("font-size", "20px")
.text("Population");
//y axis label
svg.append("text")
.attr("class", "text")
.attr("transform", "translate(" + (margin.left/4) + "," + (height/2) + ")rotate(-90)")
.style("text-anchor", "middle")
.style("font-size", "20px")
.text("GDP (PPP) per capita");
//title
svg.append("text")
.attr("class", "text")
.attr("transform", "translate(0," + margin.top/3 + ")")
.style("text-anchor", "left")
.style("font-size", "25px")
.text("Personal freedom score for world countries, 2016")
//subtitle
svg.append("text")
.attr("class", "text")
.attr("transform", "translate(0," + margin.top/1.6 + ")")
.style("text-anchor", "left")
.style("font-size", "20px")
.style("font-style", "italic")
.text("Bubbles are colored by region and sized by personal freedom score")
return svg.node();
}
Insert cell
Insert cell
Insert cell
xScale = d3.scaleLog()
.domain(d3.extent(freedom_2016, d => d.population)).nice()
.range([margin.left, width-margin.right]);
Insert cell
yScale = d3.scaleLog()
.domain(d3.extent(freedom_2016, d => d.gdp_ppp_cap)).nice()
.range([height - margin.bottom, margin.top]);
Insert cell
aScale = d3.scaleSqrt()
.domain([0, d3.max(freedom_2016, d => d.pf_score)])
.range([0, 10]);
Insert cell
//this is too many colors, change somehow later
colorScale = d3.scaleOrdinal()
.domain(d3.map(freedom_2016, d => d.region).keys())
.range(colors);
Insert cell
Insert cell
xAxis = g => g
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(xScale))
.call(g => g.select(".domain").remove());
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(yScale))
.call(g => g.select(".domain").remove());
Insert cell
function make_x_gridlines() {
return d3.axisBottom(xScale)
.ticks(5)
};
Insert cell
function make_y_gridlines() {
return d3.axisLeft(yScale)
.ticks(3)
};
Insert cell
Insert cell
width = 960
Insert cell
height = 800
Insert cell
margin = ({top:100, right:20, bottom: 70, left: 60})
Insert cell
colors = ["#F9FB21", "#FF9C59", "#f8a500", "#f46b85", "#FF4545", "#63FF6E", "#1dc875", "#1CBDEC", "#1f83ff", "#9933FF"]
Insert cell
html`<style> .text {
font-family: "Helvetica";}
.grid {
font-family: "Helvetica";}
div.tooltip {
font-family: "Helvetica";
position: absolute;
text-align: left;
padding: 0.5em;
font: 0.8em;
background: rgb(255, 255, 255);
border: 1px solid rgba(0, 0, 0, 0.4);
border-radius: 0.5em;
pointer-events: none;
}
</style>`
Insert cell
decFormat = d3.format(".2f")
Insert cell
bigFormat = d3.format(",.0f")
Insert cell
/*
div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0)
*/
Insert cell
function tooltipMouseOver(d, i) {
let el = d3.select("body");
el
.transition()
.duration(100)
.style("opacity", 0.9)
.style("stroke", "black")
.style("stroke-width", "2px")
.style("stroke-opacity", 0.7);
let div = el
.append("g")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);

div
.html(`
Country: ${d.datum['countries']} </br>
Personal Freedom Score: ${decFormat(d.datum['pf_score'])} </br>
Population: ${bigFormat(d.datum['population'])} </br>
GDP per capita: ${bigFormat(d.datum['gdp_ppp_cap'])}
`)
.style("opacity", 0.9)
.style("left", (d3.event.pageX + 28) + "px")
.style("top", (d3.event.pageY - 28) + "px");

}

Insert cell
function tooltipMouseOut(d, i) {
let el = d3.selectAll(".tooltip");
el.each(function() {
el.remove();
});

}
Insert cell
Insert cell
d3 = require("d3")
Insert cell
Insert cell
Insert cell
Insert cell
freedom = d3.csv("https://gist.githubusercontent.com/will-r-chase/434bed30526ba45293acd6dcb9349e82/raw/c3665bed9d32ebdede80aa3da53ca54e9dc7150e/human_freedom_gdp_pop.csv", d3.autoType)
Insert cell
freedom_2016 = freedom.filter(obj => {return obj.year === 2016})
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more