Published
Edited
Mar 31, 2021
Insert cell
md`# Project 3: D3`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart_force = {
replay;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, chart_param.width, chart_param.height]);
// const svg = d3.select(DOM.svg(chart_param.width, chart_param.height));
const nodes1 = nodes.map(d => Object.create(d));
const g = svg.append("g").attr("class", ".node");
svg.append("g")
.attr("class", "legend legend--ordinal")
.attr("transform", "translate(20,40)")
.attr("font-size", "10px");
svg.append("text").attr("x", 10).attr("y", 20).text("Top 10 AirBNB Earners in Boston, " + time).style("font-size", "15px").attr("alignment-baseline","middle")
svg.select(".legend")
.call(legend);
const tooltip = d3
.select('body')
.append('div')
.attr('class', 'd3-tooltip')
.style('position', 'absolute')
.style('z-index', '10')
.style('visibility', 'hidden')
.style('padding', '10px')
.style('background', 'rgba(0,0,0,0.6)')
.style('border-radius', '4px')
.style('color', '#fff')
.text('a simple tooltip');

const sim = d3.forceSimulation(nodes1)
.force("x", d3.forceX(x(0.5)).strength(.2))
.force("y", d3.forceY(y(0.5)).strength(.2))
.force('charge', d3.forceManyBody().strength(-10).distanceMax(1000))
.force("collide", d3.forceCollide().radius(d => d.r + 2));
const node = g.selectAll(".node")
.data(nodes1).enter()
.append("circle")
.classed("node", true)
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("fill", d => color(d.group))
.on('mouseover', function (event,d, i) {
tooltip
.html(`
<div style='float: right'>
Host Name: ${d.host_name} <br/>
Listings: ${d.listings_count} <br/>
Monthly Revenue: ${d3.format("$,.6r")(d.revenue)}
</div>`)
.style('visibility', 'visible');
})
.on('mousemove', function (event) {
tooltip
.style('top', event.pageY - 10 + 'px')
.style('left', event.pageX + 10 + 'px');
})
.on('mouseout', function (event) {
tooltip.html(``).style('visibility', 'hidden');
});
node.transition()
.delay((d, i) => Math.random() * 500)
.duration(750)
.attrTween("r", d => {
const i = d3.interpolate(0, d.r);
return t => d.r = i(t);
});
sim.on("tick", () => {
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
svg.call(d3.zoom()
.extent([[0, 0], [chart_param.width * 2, chart_param.height * 2]])
.scaleExtent([-100, 100])
.on("zoom", zoomed));

function zoomed({transform}) {
g.attr("transform", transform);
}
return svg.node()
}
Insert cell
colorscheme = d3.schemeSpectral[11]
Insert cell
// color
color = d3.scaleOrdinal(d3.range(11),colorscheme)
Insert cell
legend_color = d3.scaleOrdinal(legend_array, colorscheme.slice(1, 11))

Insert cell
legend_array = {
var empty = []
for (var i = 0; i < 10; i++) {
if (nodes[i].host_name === "") {
empty[i] = (i + 1) + " – No Name"
} else {
empty[i] = (i + 1) + " – " + nodes[i].host_name
}
}
return empty
}
Insert cell
legend = d3Legend.legendColor()
.shape("path", d3.symbol().type(d3.symbolSquare).size(100)())
// Try commenting shapePadding() to see the difference
.shapePadding(15) // cell padding
.labelOffset(10) // label offset from the shape
.scale(legend_color)
Insert cell
x = d3.scaleLinear()
.domain([0, 1])
.range([chart_param.margin.left, chart_param.width - chart_param.margin.right]);
Insert cell
y = d3.scaleLinear()
.domain([0, 1])
.range([chart_param.height - chart_param.margin.bottom, chart_param.margin.top]);
Insert cell
r = d3.scaleLinear()
.domain(data_range)
.range([.01, .5]);
Insert cell
// x, y and r taken from https://observablehq.com/@ben-tanen/a-tutorial-to-using-d3-force-from-someone-who-just-learned-how
Insert cell
revenue_array = [parseFloat(d3.min(data, d => d.revenue)),parseFloat(d3.max(data, d => d.revenue))]
Insert cell
data_range = d3.scaleSequential(revenue_array).range()
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