Jacky Zhao
2022-05-02 9ba0a4b34fa2e4993b8be021ee79d10d2674eba4
assets/js/graph.js
@@ -47,42 +47,42 @@
  const drag = simulation => {
    function dragstarted(event, d) {
      if (!event.active) simulation.alphaTarget(1).restart();
      d.fx = d.x;
      d.fy = d.y;
      if (!event.active) simulation.alphaTarget(1).restart()
      d.fx = d.x
      d.fy = d.y
    }
    function dragged(event, d) {
      d.fx = event.x;
      d.fy = event.y;
      d.fx = event.x
      d.fy = event.y
    }
    function dragended(event, d) {
      if (!event.active) simulation.alphaTarget(0);
      d.fx = null;
      d.fy = null;
      if (!event.active) simulation.alphaTarget(0)
      d.fx = null
      d.fy = null
    }
    const noop = () => { }
    return d3.drag()
      .on("start", enableDrag ? dragstarted : noop)
      .on("drag", enableDrag ? dragged : noop)
      .on("end", enableDrag ? dragended : noop);
      .on("end", enableDrag ? dragended : noop)
  }
  const height = 250
  const height = Math.max(document.getElementById("graph-container").offsetHeight, 250)
  const width = document.getElementById("graph-container").offsetWidth
  const simulation = d3.forceSimulation(data.nodes)
    .force("charge", d3.forceManyBody().strength(-30))
    .force("link", d3.forceLink(data.links).id(d => d.id))
    .force("center", d3.forceCenter());
    .force("link", d3.forceLink(data.links).id(d => d.id).distance(40))
    .force("center", d3.forceCenter())
  const svg = d3.select('#graph-container')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr("viewBox", [-width / 2, -height / 2, width, height]);
    .attr("viewBox", [-width / 2, -height / 2, width, height])
  if (enableLegend) {
    const legend = [
@@ -115,19 +115,22 @@
    .data(data.nodes)
    .enter().append("g")
  // calculate radius
  const nodeRadius = (d) => {
    const numOut = index.links[d.id]?.length || 0
    const numIn = index.backlinks[d.id]?.length || 0
    return 3 + (numOut + numIn) / 4
  }
  // draw individual nodes
  const node = graphNode.append("circle")
    .attr("class", "node")
    .attr("id", (d) => d.id)
    .attr("r", (d) => {
      const numOut = index.links[d.id]?.length || 0
      const numIn = index.backlinks[d.id]?.length || 0
      return 3 + (numOut + numIn) / 4
    })
    .attr("r", nodeRadius)
    .attr("fill", color)
    .style("cursor", "pointer")
    .on("click", (_, d) => {
      window.location.href = baseUrl + '/' + decodeURI(d.id).replace(/\s+/g, '-')
      window.location.href = `${baseUrl}/${decodeURI(d.id).replace(/\s+/g, '-')}/`
    })
    .on("mouseover", function(_, d) {
      d3.selectAll(".node")
@@ -154,11 +157,12 @@
      // show text for self
      d3.select(this.parentNode)
        .select("text")
        .raise()
        .select("text")
        .transition()
        .duration(200)
        .style("opacity", 1)
        .raise()
    }).on("mouseleave", function(_, d) {
      d3.selectAll(".node")
        .transition()
@@ -179,16 +183,19 @@
        .duration(200)
        .style("opacity", 0)
    })
    .call(drag(simulation));
    .call(drag(simulation))
  // draw labels
  const labels = graphNode.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .attr("dx", 0)
    .attr("dy", d => nodeRadius(d) + 8 + "px")
    .attr("text-anchor", "middle")
    .text((d) => content[d.id]?.title || d.id.replace("-", " "))
    .style("opacity", 0)
    .style("pointer-events", "none")
    .call(drag(simulation));
    .style("font-size", "0.4em")
    .raise()
    .call(drag(simulation))
  // set panning
@@ -197,10 +204,14 @@
      .extent([[0, 0], [width, height]])
      .scaleExtent([0.25, 4])
      .on("zoom", ({ transform }) => {
        link.attr("transform", transform);
        node.attr("transform", transform);
        labels.attr("transform", transform);
      }));
        link.attr("transform", transform)
        node.attr("transform", transform)
        const scale = transform.k
        const scaledOpacity = Math.max((scale - 1) / 3.75, 0)
        labels
          .attr("transform", transform)
          .style("opacity", scaledOpacity)
      }))
  }
  // progress the simulation
@@ -216,5 +227,5 @@
    labels
      .attr("x", d => d.x)
      .attr("y", d => d.y)
  });
  })
}