Published
Edited
Oct 3, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const root = tree(bilink(d3.hierarchy(data)
.sort((a, b) => d3.ascending(a.height, b.height) || d3.ascending(a.data.name, b.data.name))));

const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -width / 2, width, width]);

const node = svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 6)
.selectAll("g")
.data(root.leaves())
.join("g")
.attr("transform", d => `rotate(${d.x * 180 / Math.PI - 90}) translate(${d.y},0)`)
.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.x < Math.PI ? 6 : -6)
.attr("text-anchor", d => d.x < Math.PI ? "start" : "end")
.attr("transform", d => d.x >= Math.PI ? "rotate(180)" : null)
.text(d => d.data.name)
.each(function(d) { d.text = this; })
.on("mouseover", overed)
.on("mouseout", outed)
.call(text => text.append("title").text(d => `${id(d)}
-> contient ${d.outgoing.length} elements materiel
-> est contenu dans ${d.incoming.length} elements materiel`));

const link = svg.append("g")
.attr("stroke", colornone)
.attr("fill", "none")
.selectAll("path")
.data(root.leaves().flatMap(leaf => leaf.outgoing))
.join("path")
.style("mix-blend-mode", "multiply")
.attr("d", ([i, o]) => line(i.path(o)))
.each(function(d) { d.path = this; });

function overed(event, d) {
link.style("mix-blend-mode", null);
d3.select(this).attr("font-weight", "bold");
d3.selectAll(d.incoming.map(d => d.path)).attr("stroke", colorin).raise();
d3.selectAll(d.incoming.map(([d]) => d.text)).attr("fill", colorin).attr("font-weight", "bold");
d3.selectAll(d.outgoing.map(d => d.path)).attr("stroke", colorout).raise();
d3.selectAll(d.outgoing.map(([, d]) => d.text)).attr("fill", colorout).attr("font-weight", "bold");
}

function outed(event, d) {
link.style("mix-blend-mode", "multiply");
d3.select(this).attr("font-weight", null);
d3.selectAll(d.incoming.map(d => d.path)).attr("stroke", null);
d3.selectAll(d.incoming.map(([d]) => d.text)).attr("fill", null).attr("font-weight", null);
d3.selectAll(d.outgoing.map(d => d.path)).attr("stroke", null);
d3.selectAll(d.outgoing.map(([, d]) => d.text)).attr("fill", null).attr("font-weight", null);
}

return svg.node();
}
Insert cell
Insert cell
/*
source=[
{
"name": "ZONE1.ORDINATEUR.TABLETTE.(ORDINATEUR-2022-01-03)",
"size": 1,
"imports": []
},
{
"name": "ZONE1.CPU.AMD.(CPU-2022-01-14)",
"size": 1,
"imports": []
},
{
"name": "ZONE1.MEMORY.DDR4.(MEMORY-2022-01-16)",
"size": 4,
"imports": []
},
{
"name": "ZONE1.MEMORY.DDR3.(MEMORY-2022-01-16)",
"size": 4,
"imports": []
},
{
"name": "ZONE1.MEMORY.DDR4.(MEMORY-2022-01-14)",
"size": 4,
"imports": []
},
{
"name": "ZONE1.MEMORY.DDR3.(MEMORY-2022-01-03)",
"size": 4,
"imports": []
}
]
*/
Insert cell
//data = hierarchy(await FileAttachment("flare.json").json())
data = hierarchy(source)

Insert cell
Insert cell
Insert cell
Insert cell
colorin = "#00f"
Insert cell
colorout = "#f00"
Insert cell
colornone = "#ccc"
Insert cell
width = 600
Insert cell
radius = width / 2
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//import {select} from "@jashkenas/inputs"
Insert cell
Insert cell
function fileInput({initialValue, accept = ""} = {}) {
const form = html`<form><input name=i type="file" accept="${accept}">`;
form.i.onchange = () => {
form.value = form.i.multiple ? form.i.files : form.i.files[0];
form.dispatchEvent(new CustomEvent("input"));
};
form.value = initialValue;
return form;
}

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