3

I created a d3 force layout and I take data from different sources. Sometimes there may be 20 nodes, sometimes 600 - it varies with each dataset. The thing i would like to do is to make a uniform way for the layout to be fully visible when it is initially loaded. Of course the user can afterwards zoom/drag/pan, but I would like him to see the full layout when it is initially loaded.

This is the size of my svg, and the example sizes of possible datasets. Current situation

This is how I would like to see it when it starts. the whole dataset should be visible within the SVG. What i need Right now i'm trying to achieve this by checking how many nodes there are within a dataset, and scale down the 'g' element which contains them. This, however, i feel is a pretty clumsy way of doing it, plus it gives me some bugs when dragging. See code below.

Is there a smarter way to do this?

   var width = 1200,
        height = 800;

    var min_zoom = 0.5;
    var max_zoom = 10;
    var scale = 0.5;

    var zoom = d3.behavior.zoom()
        .translate([100,50])
        .scale(scale)
        .scaleExtent([min_zoom,max_zoom]);

var drag = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

    var force = cola.d3adaptor()
       .linkDistance(130)
       .avoidOverlaps(true)
       //.jaccardLinkLengths(40, 0.7)
       .handleDisconnected(false)
      .size([700, 500]);

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height)
        .call(zoom.on("zoom", zoomed));
        //.attr("transform","scale(1)");

    var g = svg.append("g")
                .attr("id", "gelem")
                .attr("transform", "translate(100,50)");

     force
          .nodes(nodes)
          .links(links)
          .groups(groups);


          nodes.forEach(function (node){
            node.height = 60;
            node.width = 60;
          })

          force.start(5,5,5);

     var group = g.selectAll(".group")
                .data(groups)
              .enter().append("rect")
                .attr("rx", 8).attr("ry", 8)
                //.classed("group", true)
                .attr("class", "group")
                .style("fill", function (d, i) { return color(i); });
                //.call(force.drag);

      var link = g.selectAll(".link")
          .data(links)
        .enter().append("line")
          .attr("class", "link")
          .style("stroke-width", function(d) { return Math.sqrt(d.value); });


      var node = g.selectAll(".node")
          .data(nodes)
            .enter().append("g")
          .attr("class", "node");
          //.call(force.drag);

      node.append("image")
          .attr("xlink:href", function(d){ return "../icons/"+d.type+".png";})
          .attr("x", -25)
          .attr("y", -25)
          .attr("width", 50)
          .attr("height", 50);

     function scaleContainer(nodes){
            if (nodes.length>200){ scale = 0.6;}
            if (nodes.length>400){ scale = 0.4;}
            if (nodes.length>500) { scale = 0.3;}
             //var height = document.getElementById("gelem").getBBox().height;
             //var width = document.getElementById("gelem").getBBox().width;
             //console.log("w/h of g element: " + height + ', '+ width);
             //console.log("g transform" ,g.attr("transform"));
             g.attr("transform", "translate(100,50) scale(" + scale + ")");
             console.log("svg scale2", g.attr("transform"));
          }

          scaleContainer(nodes);
function zoomed() {
    console.log("translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

  function dragstarted(d) {
    d3.event.sourceEvent.stopPropagation();
    d3.select(this).classed("dragging", true);
  }

  function dragged(d) {
    d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
  }

  function dragended(d) {
    d3.select(this).classed("dragging", false);
}

0 Answers0