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.