Published
Edited
Jul 2, 2019
1 star
Insert cell
md`# 2d scatterplot`
Insert cell
viewof currentValueX = html`<input type=range min=0 max=50 value=10 />`
Insert cell
viewof currentValueY = html`<input type=range min=0 max=50 value=10 />`
Insert cell
{
var height = 400;
var svg = d3.select(DOM.svg(width, height))
var chart = svg.append('g')
.attr('transform', `translate(${20}, ${20})`);
scatter({
width: width - 20,
height: height - 20,
container: chart,
criteria: [
'income_pov_p',
'multidim_pov_p'
],
currentValueX: currentValueX,
currentValueY: currentValueY,
data: data
});
return svg.node()
}
Insert cell
function scatter (params) {
var width = params.width || 400,
height = params.height || 400,
margin = {
top: 5,
right: 15,
bottom: 20,
left: 35
},
container = params.container,
criteria = params.criteria,
data = params.data,
translation = params.translation || [0, 0],
chartVisible = params.visible || true,
colors = {
green: params.colors ? params.colors.green : '#1BBC9B',
grey: params.colors ? params.colors.grey: '#E1E5EC'
},
circleRadius = 3,
chart;
function main () {
// calculations
var chartWidth = width - margin.left - margin.right;
var chartHeight = height - margin.top - margin.bottom;
var criteriaX = criteria[0];
var criteriaY = criteria[1];
var dataExtentX = extent(data, d => +d[criteriaX]);
var dataExtentY = extent(data, d => +d[criteriaY]);
var currentValueX = params.currentValueX || dataExtentX[0];
var currentValueY = params.currentValueY || dataExtentY[0];

var xScale = scaleLinear()
.range([0, chartWidth])
.domain(dataExtentX);
var yScale = scaleLinear()
.range([chartHeight, 0])
.domain(dataExtentY);
// drawing
chart = patternify(container, 'g', 'scatter')
.attr('pointer-events', 'none')
.attr('transform', `translate(${translation[0]}, ${translation[1]})`)
.attr('opacity', chartVisible ? 1 : 0);
var innerChart = patternify(container, 'g', 'scatter-inner')
.attr('pointer-events', 'none')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
var xAxis = patternify(innerChart, 'g', 'x-axis')
.attr('transform', `translate(0, ${chartHeight})`)
.call(
axisBottom(xScale)
)

var yAxis = patternify(innerChart, 'g', 'y-axis')
.call(
axisLeft(yScale)
);
var circle = patternify(innerChart, 'circle', 'dot', data)
.attr('r', circleRadius)
.attr('cx', d => xScale(+d[criteriaX]))
.attr('cy', d => yScale(+d[criteriaY]))
.attr('fill', d => {
var x = +d[criteriaX];
var y = +d[criteriaY];
if (x >= currentValueX && y >= currentValueY) {
return colors.green
}
return colors.grey
})
var currentLineX = patternify(innerChart, 'line', 'current-line-x')
.attr('x1', xScale(Math.ceil(currentValueX)) - circleRadius)
.attr('x2', xScale(Math.ceil(currentValueX)) - circleRadius)
.attr('y1', 0)
.attr('y2', chartHeight)
.attr('stroke', '#2F353B')
.attr('stroke-width', '1.5px')
.attr('stroke-dasharray', '5 5')
var currentLineY = patternify(innerChart, 'line', 'current-line-y')
.attr('y1', yScale(Math.ceil(currentValueY)) + circleRadius)
.attr('y2', yScale(Math.ceil(currentValueY)) + circleRadius)
.attr('x1', 0)
.attr('x2', chartWidth)
.attr('stroke', '#2F353B')
.attr('stroke-width', '1.5px')
.attr('stroke-dasharray', '5 5')
return main;
}
return main();
}
Insert cell
// handles d3.js update, enter and exit selections
function patternify (container, elementTag, selector, data = null) {
data = data || [selector]
// Pattern in action
var selection = container.selectAll('.' + selector).data(data, (d, i) => {
if (typeof d === 'object') {
if (d.id) {
return d.id
}
}
return i
})
selection.exit().remove()
selection = selection.enter().append(elementTag).merge(selection)
selection.attr('class', selector)
return selection
}
Insert cell
extent = d3.extent
Insert cell
scaleLinear = d3.scaleLinear
Insert cell
axisLeft = d3.axisLeft
Insert cell
axisBottom = d3.axisBottom
Insert cell
data = d3.csv('https://gist.githubusercontent.com/giorgi-ghviniashvili/793aa3d52f06ff887f8b806493b70a01/raw/b0696b66503c9c2034e7ee7ed798646eb7558d49/data.csv')
Insert cell
d3 = require('d3')
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