Public
Edited
Dec 11, 2023
Paused
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
const displayGroup = svg.append('g').attr('id', 'displayGroup');
const mapGroup = displayGroup.append('g').attr('id', 'mapGroup');
mapGroup.selectAll('path')
.data(geoData.features)
.enter()
.append('path')
.attr("id", function (d) {
return d.properties['NAME'];
})
.attr('d', geoGenerator);
const dataGroup = displayGroup.append('g').attr('id', 'dataGroup');

// Bind the data to the SVG and create a circle for each row
const points = dataGroup.selectAll('circle')
.data(cutUniData)
.enter()
.append('circle')
.attr('cx', function (d) { return d.projected_x; })
.attr('cy', function (d) { return d.projected_y; })
.attr('r', function (d) { return radiusScale(Math.sqrt(d.total)); })
.attr('id', function (d) { return d.css_id; });
// Create a force simulation
var simulation = d3.forceSimulation(cutUniData)
.force('collide', d3.forceCollide().radius(function (d) { return d.radius + 1; }))
.force('cluster', forceCluster())
.on('tick', function () {
dataGroup.selectAll('circle')
.attr('cx', function (d) { return d.x; })
.attr('cy', function (d) { return d.y; });
});

hover(points, invalidation);


return svg.node();
}
Insert cell
d3 = require("d3@7")
Insert cell
geoData = FileAttachment("uk-and-ireland.geojson").json()
Insert cell
uniData = FileAttachment("engineering-uk-unis.csv").csv()
Insert cell
mappedUniData = uniData.map( row => ({
id: +row['Key'],
css_id: "uni_" + row['Key'],
name: row['University'],
total: +row['Total'],
latitude: +row['Latitude'],
longitude: +row['Longitude'],
projected_x: 0,
projected_y: 0,
radius: 0
})
);
Insert cell
cutUniData = mappedUniData.filter(function (d) { return d.total > 450; });
Insert cell
maxTotal = d3.max(mappedUniData, function (d) { return d.total; })
Insert cell
width = 600;
Insert cell
height = 600;
Insert cell
Insert cell
projection = d3.geoMercator().scale(1);
Insert cell
geoGenerator = d3.geoPath().projection(projection);
Insert cell
bounds = d3.geoBounds(geoData);
Insert cell
projection.fitExtent([[0, -height * 0.2], [width, height]], geoData);
Insert cell
cutUniData.forEach(function (d) {
var p = projection([d.longitude, d.latitude]);
d.projected_x = p[0];
d.projected_y = p[1];
d.radius = radiusScale(Math.sqrt(d.total));
d.x = p[0];
d.y = p[1];
});
Insert cell
function forceCluster() {
var strength = 0.2;
var nodes;
function force(alpha) {
// Push nodes towards their designated cluster centers
nodes.forEach(function (d) {
d.vx -= (d.x - d.projected_x) * strength * alpha;
d.vy -= (d.y - d.projected_y) * strength * alpha;
});
}
force.initialize = function (_nodes) {
nodes = _nodes;
};
return force;
}
Insert cell
Insert cell
Insert cell
import {hover} with {tipcontent} from "@fil/hello-tippy"
Insert cell
function tipcontent(d) {
return `${d.name}<br />${d.total}`;
}
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