Public
Edited
Jan 24, 2024
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
svg = {
const svg = DOM.svg(width, 700);
return svg;
}
Insert cell
x = d3.scaleBand().domain([0, 1, 2]).range([0, width]).padding(0.2)
Insert cell
y = d3
.scaleBand()
.domain(d3.range(Math.ceil(data.length / 3)))
.range([0, 700])
.padding(0.2)
Insert cell
Insert cell
y.bandwidth()
Insert cell
Insert cell
drag = {
return function (g, svg) {
function dragstarted(event, d) {
d3.select(this).attr("opacity", 1).attr("pointer-events", "none");
const me = d3.select(this).raise();
me.attr(
"transform",
`translate(${event.x - x.bandwidth() / 2},${
event.y - y.bandwidth() / 2
})`
);
}

function dragged(event, d, i) {
const me = d3.select(this);

me.attr(
"transform",
`translate(${event.x - x.bandwidth() / 2},${
event.y - y.bandwidth() / 2
})`
);
let xx = scaleBandInvert(x)(event.x + x.bandwidth() / 2);
let yy = scaleBandInvert(y)(event.y);
let overs = data.filter((t, i) => {
return (
(i % 3 === xx || (i % 3) + 1 === xx) &&
Math.floor(i / 3) === yy &&
t.name != me.data()[0].name
);
});
d3.select(svg)
.selectAll(".sub")
.data(overs, (d) => d.name)
.each(function (d, i) {
d3.select(this)
.select("rect")
.attr("x", overs.length === 1 ? 15 : i === 0 ? -15 : 15);
})
.exit()
.each(function (d) {
d3.select(this).select("rect").attr("x", 0);
});
}

function dragended(event, d) {
const me = d3.select(this).attr("pointer-events", "auto");
let xx = scaleBandInvert(x)(event.x + x.bandwidth() / 2);
let yy = scaleBandInvert(y)(event.y);
let overs = data.filter((t, i) => {
return (
(i % 3 === xx || (i % 3) + 1 === xx) &&
Math.floor(i / 3) === yy &&
t.name != me.data()[0].name
);
});

switchPos(me.data()[0], overs);
mutable rero = rero + 1;
}

const drag = d3
.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);

return drag(g);
};
}
Insert cell
switchPos = (from, to) => {
console.log({ from, to });
if (to) {
let pos = (to[1] || to[0]).position;

mutable data = data
.reduce((a, b) => {
if (b.name === from.name) {
return [...a, { ...b, position: pos }];
}
if (b.position < pos) {
return [...a, b];
}
if (b.position >= pos) {
return [...a, { ...b, position: b.position + 1 }];
}
}, [])
.sort((a, b) => a.position - b.position);
}
}
Insert cell
function scaleBandInvert(scale) {
var domain = scale.domain();
var paddingOuter = scale(domain[0]);
var eachBand = scale.step();
return function (value) {
var index = Math.floor((value - paddingOuter) / eachBand);
return domain[Math.max(0, Math.min(index, domain.length - 1))];
};
}
Insert cell
mutable rero = 0
Insert cell
w = (width / N) | 0
Insert cell
N = 10
Insert cell
color = d3.scaleOrdinal(d3.schemeCategory10)
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