| | |
| | | async function drawGraph(baseUrl, isHome, pathColors, graphConfig) { |
| | | |
| | | let { |
| | | depth, |
| | | enableDrag, |
| | | enableLegend, |
| | | enableZoom, |
| | | opacityScale, |
| | | scale, |
| | | repelForce, |
| | | fontSize} = graphConfig; |
| | | depth, |
| | | enableDrag, |
| | | enableLegend, |
| | | enableZoom, |
| | | opacityScale, |
| | | scale, |
| | | repelForce, |
| | | fontSize } = graphConfig; |
| | | |
| | | const container = document.getElementById("graph-container") |
| | | const { index, links, content } = await fetchData |
| | |
| | | d.fy = null |
| | | } |
| | | |
| | | const noop = () => {} |
| | | const noop = () => { } |
| | | return d3 |
| | | .drag() |
| | | .on("start", enableDrag ? dragstarted : noop) |
| | |
| | | .style("cursor", "pointer") |
| | | .on("click", (_, d) => { |
| | | // SPA navigation |
| | | window.Million.navigate(new URL(`${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/`), ".singlePage") |
| | | const targ = `${baseUrl}${decodeURI(d.id).replace(/\s+/g, "-")}/` |
| | | window.Million.navigate(new URL(targ), ".singlePage") |
| | | plausible("Link Click", { |
| | | props: { |
| | | href: targ, |
| | | broken: false, |
| | | internal: true, |
| | | graph: true, |
| | | } |
| | | }) |
| | | }) |
| | | .on("mouseover", function (_, d) { |
| | | .on("mouseover", function(_, d) { |
| | | d3.selectAll(".node").transition().duration(100).attr("fill", "var(--g-node-inactive)") |
| | | |
| | | const neighbours = parseIdsFromLinks([ |
| | |
| | | // highlight links |
| | | linkNodes.transition().duration(200).attr("stroke", "var(--g-link-active)") |
| | | |
| | | const bigFont = fontSize*1.5 |
| | | const bigFont = fontSize * 1.5 |
| | | |
| | | // show text for self |
| | | d3.select(this.parentNode) |
| | |
| | | .duration(200) |
| | | .attr('opacityOld', d3.select(this.parentNode).select('text').style("opacity")) |
| | | .style('opacity', 1) |
| | | .style('font-size', bigFont+'em') |
| | | .style('font-size', bigFont + 'em') |
| | | .attr('dy', d => nodeRadius(d) + 20 + 'px') // radius is in px |
| | | }) |
| | | .on("mouseleave", function (_, d) { |
| | | .on("mouseleave", function(_, d) { |
| | | d3.selectAll(".node").transition().duration(200).attr("fill", color) |
| | | |
| | | const currentId = d.id |
| | |
| | | linkNodes.transition().duration(200).attr("stroke", "var(--g-link)") |
| | | |
| | | d3.select(this.parentNode) |
| | | .select("text") |
| | | .transition() |
| | | .duration(200) |
| | | .style('opacity', d3.select(this.parentNode).select('text').attr("opacityOld")) |
| | | .style('font-size', fontSize+'em') |
| | | .attr('dy', d => nodeRadius(d) + 8 + 'px') // radius is in px |
| | | .select("text") |
| | | .transition() |
| | | .duration(200) |
| | | .style('opacity', d3.select(this.parentNode).select('text').attr("opacityOld")) |
| | | .style('font-size', fontSize + 'em') |
| | | .attr('dy', d => nodeRadius(d) + 8 + 'px') // radius is in px |
| | | }) |
| | | .call(drag(simulation)) |
| | | |
| | |
| | | .text((d) => content[d.id]?.title || (d.id.charAt(1).toUpperCase() + d.id.slice(2)).replace("-", " ")) |
| | | .style('opacity', (opacityScale - 1) / 3.75) |
| | | .style("pointer-events", "none") |
| | | .style('font-size', fontSize+'em') |
| | | .style('font-size', fontSize + 'em') |
| | | .raise() |
| | | .call(drag(simulation)) |
| | | |