{
const svg = html`
<svg width="${width}" height="${height}" >
<style>
.legend {
font-family: monospace;
text-transform: uppercase;
letter-spacing: 7px;
font-size: 20px;
opacity: 70%;
font-weight: 900;
text-shadow: 0 1px 0px white;
}
</style>
<linearGradient id="linearColor1" x1="0" y1="0" x2="1" y2="0">
<stop offset="95%" stop-color="#00000033"></stop>
<stop offset="100%" stop-color="#000000"></stop>
</linearGradient>
<linearGradient id="linearColor2" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="97%" stop-color="#00000033"></stop>
<stop offset="98%" stop-color="#000000"></stop>
</linearGradient>
<linearGradient id="linearColor3" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="97%" stop-color="#00000033"></stop>
<stop offset="98%" stop-color="#000000"></stop>
</linearGradient>
<linearGradient id="linearColor4" x1="0" y1="0" x2="0.64" y2="1">
<stop offset="99%" stop-color="#00000033"></stop>
<stop offset="100%" stop-color="#000000"></stop>
</linearGradient>
<circle r="${r1}" cx="${400}" cy="${350}" stroke="none" stroke-opacity="0.5" fill="none"></circle>
<circle r="${r2}" cx="${400}" cy="${350}" stroke="none" stroke-opacity="0.5" fill="none"></circle>
<circle r="${rselected}" cx="${400}" cy="${350}" stroke="none" stroke-opacity="0.5" fill="none"></circle>
<circle r="${100}" cx="${400}" cy="${350}" stroke-opacity="0.5" fill="#00000009" stroke="url(#linearColor1)"></circle>
<circle r="${175}" cx="${400}" cy="${350}" stroke-opacity="0.5" fill="none" stroke="url(#linearColor2)"></circle>
<circle r="${250}" cx="${400}" cy="${350}" stroke-opacity="0.5" fill="none" stroke="url(#linearColor3)"></circle>
<circle r="${325}" cx="${400}" cy="${350}" stroke-opacity="0.5" fill="none" stroke="url(#linearColor4)"></circle>
<text x="510" y="360" class="legend">← Selected</text>
<text x="515" y="500" class="legend">← High Relevance</text>
<text x="562" y="560" class="legend">← Low Relevance</text>
<text x="610" y="620" class="legend">← Potential Relevance</text>
</svg>`;
const node = d3.select(svg)
.selectAll()
.data(nodes)
.join("circle")
.attr("r", d => d.r)
.attr("cx", x)
.attr("cy", y)
.attr("fill", "#00000029")
const link = d3.select(svg)
.append("g")
.attr("stroke", linkColor)
.attr("stroke-opacity", 0.6)
.selectAll()
.data(links)
.join("line")
.attr("stroke-width", d => Math.sqrt(d.value));
function assignNodeToRandomTier(d) {
if(selector.includes(d.id)) return rselected;
switch(d.type) {
case "a":
case "c":
case "d":
case "g":
return r1;
break;
case "h":
return r3;
break;
default:
return r2;
}
}
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).strength(0.1))
.force('collide', d3.forceCollide().radius(d => d.r + 1))
.force("r", d3.forceRadial(d => assignNodeToRandomTier(d), 400, 350).strength(0.5))
.on("tick", ticked)
.alphaTarget(0.1);
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);
}
ticked();
invalidation.then(() => simulation.stop());
return svg;
}