Published
Edited
Apr 9, 2021
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof graph = {
const form = html`<form />`;
let iterationCount = 0;
const timeout = setInterval(() => {
form.dispatchEvent(new CustomEvent("input"));
}, nextGraph * 1000);
form.onchange = () => form.dispatchEvent(new CustomEvent("input")); // Safari
form.oninput = event => {
if (iterationCount >= maxClusters-1) {
clearInterval(timeout);
}
iterationCount++;
if (event.isTrusted) clearInterval(timeout), form.onchange = null;
// Next value
const name = faker.company.companyName();
const count = Math.random() * 15;
const connectedAmount = Math.random();
const cluster = createCluster(name, count, connectedAmount);
if (merge) {
if (!form.value) {
form.value = cluster;
} else {
form.value.nodes = [...form.value.nodes, ...cluster.nodes];
form.value.links = [...form.value.links, ...cluster.links];
}
} else {form.value = cluster; }
};
// Initial value
const name = faker.company.companyName();
// form.value = createCluster(name, 3, 0.7);
invalidation.then(() => clearInterval(timeout));
return form;
}
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height]);

const simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(forceStrength))
.force("link", d3.forceLink().id(d => d.id).distance(forceDistance))
.force("x", d3.forceX())
.force("y", d3.forceY())
// .force("x", d3.forceX().strength(0.1).x(width / 2))
// .force("y", d3.forceY().strength(0.1).y(height / 2))
// .force("collide", d3.forceCollide().strength(0.7).radius(function(d) {
// return d.radius + 0.5;
// }).iterations(2))
.on("tick", ticked);

let link = svg.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.attr("stroke-width", 1.5) // Move thise to update below
.selectAll("line");

let node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle");

function ticked() {
node.attr("cx", d => d.x)
.attr("cy", d => d.y)

link.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
}


// Terminate the force layout when this cell re-runs.
invalidation.then(() => simulation.stop());

return Object.assign(svg.node(), {
update({nodes, links}) {

// Make a shallow copy to protect against mutation, while
// recycling old nodes to preserve position and velocity.
const old = new Map(node.data().map(d => [d.id, d]));
nodes = nodes.map(d => Object.assign(old.get(d.id) || {}, d));
links = links.map(d => Object.assign({}, d));

node = node
.data(nodes, d => d.id)
.join(enter => enter.append("circle")
.attr("r", 8) // Circle radius
.attr("fill", d => color(d.group)));

link = link
.data(links, d => [d.source, d.target])
.join("line");
const enclosingCircle = d3.packEnclose(node.selectAll("circle"));
console.log(node.selectAll("circle"));
console.log(enclosingCircle);

simulation.nodes(nodes);
simulation.force("link").links(links);
simulation.alpha(1).restart();
}
});
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
update = chart.update(graph)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
createCluster('mySpace', 5, 1);
Insert cell
Insert cell
function clamp(value, min, max) {
return Math.max(Math.min(value, max), min);
}
Insert cell
Insert cell
clamp(-1, 0, 1)
Insert cell
function shuffle(array) {
// Fisher-Yates (aka Knuth) Shuffle
// https://stackoverflow.com/a/2450976
var currentIndex = array.length, temporaryValue, randomIndex;

// While there remain elements to shuffle...
while (0 !== currentIndex) {

// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;

// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}

return array;
}
Insert cell
Insert cell
shuffle(['a','b','c','d','e','f','g','h','i','j','k','l']);
Insert cell
function getPermutations(array, size) {

function p(t, i) {
if (t.length === size) {
result.push(t);
return;
}
if (i + 1 > array.length) {
return;
}
p(t.concat(array[i]), i + 1);
p(t, i + 1);
}

var result = [];
p([], 0);
return result;
}
Insert cell
Insert cell
getPermutations(['a', 'b', 'c', 'd'], 2);
Insert cell
Insert cell
color = d3.scaleOrdinal(d3.schemeTableau10)
Insert cell
height = 680
Insert cell
Insert cell
faker = require("https://unpkg.com/faker@5.1.0/dist/faker.min.js")
Insert cell
d3 = require("d3@6")
Insert cell
Inputs = require("@observablehq/inputs@0.7.17/dist/inputs.umd.min.js")
Insert cell
Range = Inputs.Range
Insert cell
Toggle = Inputs.Toggle
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