4

I used

d3.select(".graph")
  .call(d3.behavior.zoom().on("zoom", redraw)).on("dblclick.zoom", null).on("wheel.zoom", null);

function redraw() {
  console.log("here", d3.event.translate, d3.event.scale);
  g.attr("transform","translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); 
} 

to create pan, but when i create an .on event listener and call redraw() with anything other than the way i have it, it comes back with nothing for d3.event.translate and d3.event.scale, so i can't update the transform. And i've seen code out there for zooming with a button for maps, but not a graph. It must be possible some how, but i don't see how. The code i have so far is...

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>

.node {
  stroke: #000;
  stroke-width: 0px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}
.graphmap {
  border: 1px solid black;
}
</style>
</head>
<body>
<div class="graph"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

// start draw zoom buttons
var zoom = d3.select(".zoom").append("svg")
    .attr("width", 40)
    .attr("height", 40);



// start zoom behavior
var mapZoom = d3.behavior.zoom()
   .on("zoom", redraw);


function zoomButton(zoomDirection) {
  if (zoomDirection == "in") {
    var newZoom = mapZoom.scale() * 1.5; 
    var newX = 
      ((mapZoom.translate()[0] - (width / 2)) * 1.5) + width / 2;
    var newY = 
      ((mapZoom.translate()[1] - (height / 2)) * 1.5) + height / 2; 
  }
  else if (zoomDirection == "out") {
    var newZoom = mapZoom.scale() * .75;
    var newX = ((mapZoom.translate()[0] - (width / 2)) * .75) + width / 2;
    var newY = ((mapZoom.translate()[1] - (height / 2)) * .75) + height / 2;
  }
  mapZoom.scale(newZoom).translate([newX,newY]) 
  redraw();   
}

function zoomed() {
    projection.translate(mapZoom.translate()).scale(mapZoom.scale());
    d3.selectAll("path.graticule").attr("d", geoPath); 
    d3.selectAll("path.countries").attr("d", geoPath);
    d3.selectAll("circle.cities")
        .attr("cx", function(d) {return projection([d.x,d.y])[0]}) 
        .attr("cy", function(d) {return projection([d.x,d.y])[1]});
}

d3.select(".zoomin").on("click", function (){
    zoomButton("in");
    console.log(d3.behavior.zoom().event(d3.select(".zoomin")))
});


d3.select(".graph")
  .call(d3.behavior.zoom().on("zoom", redraw)).on("dblclick.zoom", null).on("wheel.zoom", null);

d3.select(".zoomin")
  .call(d3.behavior.zoom().on("zoom", redraw)).on("dblclick.zoom", redraw);

function redraw() {
  console.log("here", d3.event.translate, d3.event.scale);
  g.attr("transform","translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); 
} 


// start svg

var width = 1100,
    height = 900;

var color = d3.scale.category20();

var force = d3.layout.force()
    .gravity(.05)
    .charge(-700)
    .linkDistance(150)
    .size([width, height]);

var svg = d3.select(".graph").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "graphmap");

zoomin = svg.append("g")
    .attr("class", "zoomin");

zoomin.append("rect")
    .attr("x", 10)
    .attr("y", 10)
    .attr("width", 30)
    .attr("height", 30)
    .attr("rx", 4)
    .attr("ry", 4)
    .attr("fill", "#dadae6");



var g = svg.append('g');


d3.json("miserables.json", function(error, graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

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

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

  node.append("circle")
    .attr("r", function(d) { return Math.sqrt(d.group * 20); })
    .style("fill", function(d) { return color(d.group); })
    .attr("pointer-events", "auto")
    .attr("class", "circlenode");

  node.append("text")
    .attr("text-anchor", "right") 
    .attr("fill","black")
    .style("pointer-events", "none")
    .attr("font-size", function(d) { 20 + 'px'; })
    .attr("font-weight", function(d) { return "bold"; })
    .text( function(d) { return d.name + ' (' + d.group + ')';});

  setTimeout(function() {
    node.classed("fixed", function(d) { return d.fixed = true; });
  }, 9000);

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")";});
  });
});
function dump(obj) {
    var out = '';
    for (var i in obj) {
        out += i + ": " + obj[i] + "\n";
    }

    // or, if you wanted to avoid alerts...

    var pre = document.createElement('pre');
    pre.innerHTML = out;
    document.body.appendChild(pre)
}
</script>

</body>
</html>

You'll see i was playing around with making a zoomButton function but i don't know how to see how to set it up to make it work. I've seen some demos out there of different ideas with the zoom functionality but i don't really understand how they work and what the functions are for. And the d3 documentation doesn't seem to provide much insight. And i haven't found any tutorials that go over what each of the functions do and how to handle events. Any help an explanation of how the zoom functions actually work would be appreciated.

raz
  • 151
  • 1
  • 9
  • change the value of d3.behaviour.scale() – AJ_91 Apr 07 '15 at 15:59
  • Refer this http://stackoverflow.com/questions/7871425/is-there-a-way-to-zoom-into-a-d3-force-layout-graph – PAC Apr 07 '15 at 16:03
  • I tried changing d3.behavior.zoom.scale() Is that what you mean? It didn't work anyhow. `d3.select(".zoomin").on("click", function (){ d3.select(".graphmap") .call(zoomlistener.scale(2)) });` And i did read every post in that question. They talk about making zoom behaviors with mouse but not with a button. I know how to zoom with the mouse. It still gives me the same problem that d3.event.scale and d3.event.transition are undefined when i call. – raz Apr 07 '15 at 18:07
  • 1
    Figured it out. Thank you AJ. You lead me in the right direction. I needed to also add a `d3.behavior.zoom.event()` to my selection, and now it works! – raz Apr 07 '15 at 18:38

1 Answers1

6

It turns out to be very simple.

var zoomfactor = 1;

var zoomlistener = d3.behavior.zoom()
.on("zoom", redraw);

d3.select(".zoomin").on("click", function (){
    zoomfactor = zoomfactor + 0.2;
    zoomlistener.scale(zoomfactor).event(d3.select(".graph"));
});

d3.select(".zoomout").on("click", function (){
    zoomfactor = zoomfactor - 0.2;
    zoomlistener.scale(zoomfactor).event(d3.select(".graph"));
});

function redraw() {
  console.log("here", d3.event.translate, d3.event.scale);
  g.attr("transform","translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); 
} 

scale() sets the amount you want to zoom and event() calls the portion of the page you want to update.

raz
  • 151
  • 1
  • 9