Public
Edited
Sep 13, 2023
Fork of Simple D3
1 star
Insert cell
Insert cell
vis={
const svg = d3.select(DOM.svg()).attr("viewBox", [0, 0, width, height]);

// Viridis colored cells
svg.selectAll('.row')
.data(data)
.enter()
.append('g').attr('transform', (_, i) => `translate(0, ${i * cellSize})`)
.selectAll('.cell').data((_, i) => data[i]).enter()
.append('rect')
.attr("width", cellSize)
.attr('height', cellSize)
.attr('x', (_, i) => i * cellSize)
.attr('stroke', 'white')
.attr('stroke-width', '2px')
.attr('fill', d => d3.interpolateViridis(d/9))
.on('click', function(e, d) {
if (e.target.nodeName != 'rect') return;
let y = Math.round(e.target.getAttribute('x') / cellSize);
let x = Math.round(e.target.parentNode.getAttribute('transform').slice(13, -1) / cellSize);
target = [x,y];
path = dijkstra([0,0], target, data);
svg.select('path')
.attr('d', d3.line()(
path.map(p => [(p[1] + 0.5) * cellSize, (p[0] + 0.5) * cellSize]))
)
});

// Text labels for grid cells
// svg.selectAll('.row')
// .data(data)
// .enter()
// .append('g').attr('transform', (_, i) => `translate(0, ${(i+1) * cellSize - 4})`)
// .selectAll('.cell').data((_, i) => data[i]).enter()
// .append('text')
// .attr('x', (_, i) => i * cellSize + 4)
// .attr('class', 'label')
// .text(d => d)
svg.selectAll('.label').style('font-family', 'ui-monospace').style('font-size', '15px');

let target = [data.length - 1, data[0].length - 1];
let path = dijkstra([0,0],target, data);
svg.append("path")
.attr('d', d3.line()(path.map(p => [(p[1] + 0.5) * cellSize, (p[0] + 0.5) * cellSize])))
.attr('fill', 'none')
.style('stroke-linejoin', 'round')
.style('stroke-linecap', 'round')
.attr('stroke', 'red')
.attr('stroke-width', '5px')
return svg.node();
}
Insert cell
cellSize = width / data[0].length
Insert cell
height = Math.ceil(data.length * cellSize)
Insert cell
import { BHeap } from '@bryangingechen/dijkstras-algorithm-huge-version'
Insert cell
nbrs = [[0, 1], [1, 0], [-1, 0], [0, -1]]
Insert cell
function dijkstra(src, dest, grid) {
const Q = new BHeap(({dist}) => dist);
const dist = new Map();
const prev = new Map();
const visited = new Map();

for (let rowi = 0; rowi < grid.length; ++rowi) {
for (let celli = 0; celli < grid[rowi].length; ++celli) {
dist.set([rowi, celli].toString(), cmpv([rowi, celli], src) ? 0 : Infinity);
prev.set([rowi, celli].toString(), undefined);
Q.push({c: [rowi, celli], dist: cmpv([rowi, celli], src) ? 0 : Infinity});
}
}

let u;
while (Q.size()) {
u = Q.pop().c;
if (cmpv(u, dest)) break;

if (visited.has(u.toString())) continue;
visited.set(u.toString(), true);

for (let no of nbrs) {
let v = [no[0] + u[0], no[1] + u[1]]
if (
v[0] >= grid.length ||
v[1] >= grid[0].length ||
v[0] < 0 || v[1] < 0)
continue;
const alt = dist.get(u.toString()) + grid[v[0]][v[1]];
if (alt < dist.get(v.toString())) {
dist.set(v.toString(), alt);
prev.set(v.toString(), u);
Q.push({c: v, dist: alt});
}
}
}
let path = [u];
while (prev.get(path[path.length - 1].toString()) != undefined)
path.push(prev.get(path[path.length - 1].toString()))
path.reverse()
return path;
}
Insert cell
dijkstra([0,0], [23, 15], data)
Insert cell
cmpv = (a,b) => a[0] == b[0] && a[1] == b[1]
Insert cell
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