Published
Edited
May 21, 2019
1 fork
4 stars
Insert cell
md`# ArtsEd Bubble`
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
svg.append('g').call(xAxis);
svg.append('g').call(yAxis);
svg.append('defs').call(addDefs);
const tip = d3.select('body').selectAll('div.tool-tip')
.data([1]).join('div')
.attr('class', 'tool-tip').style('opacity', 0);
svg.append('g')
.selectAll('circle')
.data(data.filter(d => /[0-9a-z]{9}16[0-9a-z]{4}/i.test(d.RCDTS)))
.join('circle')
.attr('cx', d => x(d.x))
.attr('cy', d => y(d.y))
.attr('r', d => z(d.z))
.on('mouseover',d => {
tip.style('opacity', 1);
})
.on('mousemove', d => {
var rows = [];
rows.push(['School', d.School]);
rows.push([data.x, d3.format(",.2r")(d.x)]);
rows.push([data.y, d3.format(",.2r")(d.y)]);
rows.push([data.z, d3.format("($,.2f")(d.z)]);
tip.html(rows.map(row => `<span>${row[0]}:<mark>${row[1]}</mark></span>`).join(''))
.transition().duration(200)
.style('opacity', .9)
.style('left', (d3.event.pageX + 28) + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
})
.on('mouseout', d => {
tip.transition().duration(500).style('opacity', 0);
})
.style('fill', '#69b3a2')
.style('opacity', '0.7')
.attr('stroke', 'black');
return svg.node();
}
Insert cell
height = 600
Insert cell
margin = ({top: 20, right: 30, bottom: 60, left: 40})
Insert cell
z = d3.scaleLinear()
.domain(d3.extent(data, d => d.z)).nice()
.range([1, 40]);
Insert cell
x = d3.scaleLinear()
.domain(d3.extent(data, d => d.x)).nice()
.range([margin.left, width - margin.right]);
Insert cell
y = d3.scaleLinear()
.domain(d3.extent(data, d => d.y)).nice()
.range([height - margin.bottom, margin.top])
Insert cell
xAxis = g => g
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x))
.call(g => g.select('.domain').remove())
.call(g => g.append('text')
.attr('x', width - margin.right)
.attr('y', -4)
.attr('fill', '#000')
.attr('font-weight', 'bold')
.attr('text-anchor', 'end')
.attr('class', 'axis-label')
.text(data.x))
Insert cell
yAxis = g => g
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y))
.call(g => g.select('.domain').remove())
.call(g => g.select('.tick:last-of-type text').clone()
.attr('x', 4)
.attr('text-anchor', 'start')
.attr('font-weight', 'bold')
.attr('class', 'axis-label')
.text(data.y))
Insert cell
addDefs = (defs) => {
var filter = defs.append("filter")
.attr("id", "drop-shadow")
.attr("height", "130%");

// SourceAlpha refers to opacity of graphic that this filter will be applied to
// convolve that with a Gaussian with standard deviation 3 and store result
// in blur
filter.append("feGaussianBlur")
.attr("in", "SourceAlpha")
.attr("stdDeviation", 5)
.attr("result", "blur");

// translate output of Gaussian blur to the right and downwards with 2px
// store result in offsetBlur
filter.append("feOffset")
.attr("in", "blur")
.attr("dx", 5)
.attr("dy", 5)
.attr("result", "offsetBlur");

// overlay original SourceGraphic over translated blurred opacity by using
// feMerge filter. Order of specifying inputs is important!
var feMerge = filter.append("feMerge");

feMerge.append("feMergeNode")
.attr("in", "offsetBlur")
feMerge.append("feMergeNode")
.attr("in", "SourceGraphic");
}
Insert cell
data = Object.assign(await d3.csv('https://gist.githubusercontent.com/amuqeet/3fa461a8fa4828bd20de6ba560804d5b/raw/f299fe6877babb66ae0041f111c5c29a4824e907/mike-data-2017.csv', ({RCDTS, School, 'ALLCourses': x, 'FACourses': y, 'iepp': z}) => ({RCDTS, School, x: +x, y: +y, z: +z})), {x: 'All Courses', y: 'Fine Arts Courses', z: 'Instructional Expenditure Per Pupil'})
Insert cell
d3 = require("d3@5")
Insert cell
html`
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<style>
body{
font-family: 'Roboto', sans-serif;
}

.tool-tip{
position: absolute;
padding: 8px;
margin-top: -20px;
font-size: 1em;
background: #ddd;
pointer-events: none;
}

.tool-tip span{
display:block;
}

.tool-tip mark{
font-weight:600;
margin-left: 0.2em;
background-color: transparent;
color: inherit !important;
}
.axis-label{
font-size: 1.2em;
}
circle{
&:hover {
-webkit-filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));
filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));

}
}
</style>
`
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