Published
Edited
May 28, 2020
Fork of Arc diagram
Insert cell
md`# 「敦睦艦隊」相關文章互相引用圖表

此圖表示同一文章在不同新聞網站的co-occurrences。線越粗代表出現相同內容的文章數目越多,可以hover到新聞網站看個別網站的connections。`
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));

svg.append("style").text(`

.hover path {
stroke: #ccc;
}

.hover text {
fill: #ccc;
}

.hover g.primary text {
fill: black;
font-weight: bold;
}

.hover g.secondary text {
fill: #333;
}

.hover path.primary {
stroke: #333;
stroke-opacity: 1;
}

`);

const label = svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(graph.nodes)
.join("g")
.attr("transform", d => `translate(${margin.left},${d.y = y(d.id)})`)
.call(g => g.append("text")
.attr("x", -6)
.attr("dy", "0.35em")
.attr("fill", d => d3.lab(color(d.group)).darker(2))
.text(d => d.id))
.call(g => g.append("circle")
.attr("r", 3)
.attr("fill", d => color(d.group)));

const path = svg.insert("g", "*")
.attr("fill", "none")
.attr("stroke-opacity", 0.6)
.attr("stroke-width", 1.5)
.selectAll("path")
.data(graph.links)
.join("path")
.attr("stroke", d => d.source.group === d.target.group ? color(d.source.group) : "#aaa")
.attr("d", arc)
.attr("stroke-width", d => Math.sqrt(d.value));

const overlay = svg.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.selectAll("rect")
.data(graph.nodes)
.join("rect")
.attr("width", margin.left + 40)
.attr("height", step)
.attr("y", d => y(d.id) - step / 2)
.on("mouseover", d => {
svg.classed("hover", true);
label.classed("primary", n => n === d);
label.classed("secondary", n => n.sourceLinks.some(l => l.target === d) || n.targetLinks.some(l => l.source === d));
path.classed("primary", l => l.source === d || l.target === d).filter(".primary").raise();
})
.on("mouseout", d => {
svg.classed("hover", false);
label.classed("primary", false);
label.classed("secondary", false);
path.classed("primary", false).order();
});

function update() {
y.domain(graph.nodes.sort(viewof order.value).map(d => d.id));

const t = svg.transition()
.duration(750);

label.transition(t)
.delay((d, i) => i * 20)
.attrTween("transform", d => {
const i = d3.interpolateNumber(d.y, y(d.id));
return t => `translate(${margin.left},${d.y = i(t)})`;
});

path.transition(t)
.duration(750 + graph.nodes.length * 20)
.attrTween("d", d => () => arc(d));

overlay.transition(t)
.delay((d, i) => i * 20)
.attr("y", d => y(d.id) - step / 2);
}

viewof order.addEventListener("input", update);
invalidation.then(() => viewof order.removeEventListener("input", update));

return svg.node();
}
Insert cell
function arc(d) {
const y1 = d.source.y;
const y2 = d.target.y;
const r = Math.abs(y2 - y1) / 2;
return `M${margin.left},${y1}A${r},${r} 0,0,${y1 < y2 ? 1 : 0} ${margin.left},${y2}`;
}
Insert cell
y = d3.scalePoint(graph.nodes.map(d => d.id).sort(d3.ascending), [margin.top, height - margin.bottom])
Insert cell
margin = ({top: 20, right: 20, bottom: 20, left: 100})
Insert cell
height = (data.nodes.length - 1) * step + margin.top + margin.bottom + 100
Insert cell
step = 20
Insert cell
color = d3.scaleOrdinal(graph.nodes.map(d => d.group).sort(d3.ascending), d3.schemeCategory10)
Insert cell
graph = {
const nodes = data.nodes.map(({id, group}) => ({
id,
sourceLinks: [],
targetLinks: [],
group
}));

const nodeById = new Map(nodes.map(d => [d.id, d]));

const links = data.links.map(({source, target, value}) => ({
source: nodeById.get(source),
target: nodeById.get(target),
value
}));

for (const link of links) {
const {source, target, value} = link;
source.sourceLinks.push(link);
target.targetLinks.push(link);
}

return {nodes, links};
}
Insert cell
data = FileAttachment("site_groups@1.json").json()
Insert cell
d3 = require("d3@5")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more