JSFiddle - React, Tailwind, and code Playground

by KgomDr

HTML

<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <title>Painful zoom with D3.js</title>
  <script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body><div id='graph' class='graphcontainer'></div>
</body>
</html>

CSS

.graphcontainer {
  width: 500px;
  height: 500px;
  background-color: #eee;
}

svg {
  overflow: visible
}

JavaScript

// When I use this for real, altering scale is a lot easier than re-tweaking all of the force properties
const SCALE = 1;
const SHOW_BROKEN = true;

class Graph {
  constructor() {}

  build(id) {
    let self = this;
    this.parentDiv = d3.select(id);
    this.parentDiv.selectAll('*').remove();

    this.parentSvg = this.parentDiv.append("svg")
      .attr("width", '100%')
      .attr("height", '100%');

    this.parentSvg.attr("viewBox", [0, 0, this.current_width * SCALE, this.current_height * SCALE]);

    this.svg = this.parentSvg.append("g");
    this.parentSvg.call(d3.zoom()
      .extent([
        [0, 0],
        [this.current_width, this.current_height]
      ])
      .scaleExtent([0.5, 4])
      .on("zoom", zoomed));

    function zoomed() {
      if (SHOW_BROKEN) {
        // This does not work.  Im confused 
        d3.select(this).attr("transform", d3.event.transform);
      } else {
        // This works pretty much perfectly
        self.svg.attr("transform", d3.event.transform);
      }
    }

    this.run_viz();
  }

  run_viz() {
    let self = this;
    let h = this.current_height;
    let w = this.current_width;
    let nodeEdgeData = this.get_data();

    this.simulation = d3.forceSimulation();
    /*
    This controls depth, and allows us to add individual nodes and edges dynamically without
    having to worry about them doing weird stacking.  Not at all useful in this example, but
    something I wish someone had explained to me earlier
    */
    this.linkGroup = this.svg.append("g")
      .attr("class", "link");

    this.nodeGroup = this.svg.append("g")
      .attr("class", "node");

    let link = this.linkGroup
      .selectAll(".edgeline")
      .data(nodeEdgeData.edges)
      .enter()
      .append("path")
      .attr('class', "edgeline")
      .attr('stroke-width', 2)
      .attr('stroke', "#999")
      .attr('fill', 'none');

    let node = this.nodeGroup
      .selectAll(".nodeEntry")
      .data(nodeEdgeData.nodes)
     ...