Search code examples
svgd3.jszooming

Zooming into defs in force-directed graphs


I am currently implementing a d3JS force directed graph for which I have created a marker def that is appended to the links(paths).

The problem is that when I use my zoom function, the markers just disappear and the same happens when i pan around.

How do i make the markers keep the relative position in the force-directed graph?

Here is my zooming code:

this.zoom = d3.zoom().on('zoom', (e) => {
        const transform = e.transform;
        this.chart.selectAll("path").attr('transform', transform);
        this.chart.selectAll("circle").attr('transform', transform);
        this.chart.selectAll("marker").attr('transform', transform);
      });

      this.chart.call(this.zoom);

& here is the relevant marker def and code:

//link arrow
      this.chart.append("defs").selectAll("marker")
        .data(["dominating"])
        .enter().append("marker")
        .attr('markerUnits', 'userSpaceOnUse')
        .attr("id", function (d) {
          return d;
        })
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", 30)
        .attr("refY", 0)
        .attr("markerWidth", 4)
        .attr("markerHeight", 5)
        .attr("orient", "auto-start-reverse")
        .append("path")
        .attr("d", "M0,-5L10,0L0,5")
        .attr("fill", "red");

this.link = this.link
        .data(edges, d => [d.source, d.target])
        .join(enter => enter.insert("path", "circle")
          .attr("fill", "none")
          .attr("stroke-width", 1)
          .attr("stroke", red)
          .attr("marker-end", "url(#dominating)"));

Thanks in advance!


Solution

  • I have found a solution that seems to work. Basically instead of zooming into certain elements we zoom into the entire graph.

    //you need to add an inbetween element where you append all other elements (nodes,links, etc)
    this.scene = this.chart.append("g");
    
    //we apply the zoom on the child element
    this.zoom = d3.zoom().on('zoom', (e) => {
        this.scene.attr("transform", e.transform);
    });
    this.chart.call(this.zoom);
    

    Hope this helps!