Reputation: 8150
I am throwing an error on my implementation of Mike Bostock's zoom to bounding box II.
The error stops the zoom mid-way and locks up the map if you scroll during the zooming event.
Any ideas on fixing? The error is present on Bostock's example.
Here is a screenshot of the error:
The code:
var width = 500,
height = 370,
active = d3.select(null);
var projection = d3.geo.albersUsa()
.scale(675)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select(".app-map")
.append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g")
.attr("class", "app-counties-map");
function ready(error, us) {
g.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("class", "app-counties")
.attr("d", path)
.on("click",clicked);
function clicked(d) {
if (active.node() === this) return reset();
active.classed("active", false);
active = d3.select(this).classed("active", true);
var bounds = path.bounds(d),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][3] - bounds[0][4],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][5] + bounds[1][6]) / 2,
scale = 3.5,
translate = [width / 2 - scale * x, height / 2 - scale * y];
svg.transition()
.duration(450)
.call(zoom.translate(translate).scale(scale).event);
};
function reset() {
active.classed("active", false);
active = d3.select(null);
svg.transition()
.duration(450)
.call(zoom.translate([0, 0]).scale(1).event);
};
var zoom = d3.behavior.zoom()
.translate([0, 0])
.scale(1)
.scaleExtent([1, 8])
.on("zoom", zoomed);
svg.on("click", stopped, true);
svg
.call(zoom)
.call(zoom.event);
function zoomed() {
g.style("stroke-width", 1.5 / d3.event.scale + "px");
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
function stopped() {
if (d3.event.defaultPrevented) d3.event.stopPropagation();
}
}
queue()
.defer(d3.json, "./data/us (2).json")
.await(ready);
Upvotes: 0
Views: 545
Reputation: 46
I believe that the problem is happening because the mouse wheel event is trying to zoom while the zoom transition animation from click event is still playing ( I didn't get the error in chrome but in IE ).
You could turn the mouse-wheel event off at the beginning of the click event and enable it back on after the animation/transition finish.
In order to wait for the transition to finish, I've used .each, but maybe .call can be used as well.
Added 20150501 8:24PM PST
I am off work now so I can explain in more detail.
var _wheelZoomEvent = svg.on("wheel.zoom");
function clicked(d) {
svg.on("wheel.zoom", null);
While click transition is executing, we want to prevent the mouse wheel event from triggering another zoom transition. svg.on("wheel.zoom") is returning the reference to the event handler, so that I can reattach when the transition is complete. svg.on("wheel.zoom", null) detaches the event handler from mousewheel event.
After the transition completes we need to re-attach the mousewheel event back to the svg object.
svg.transition()
.duration(750)
.call(zoom.translate([0, 0]).scale(1).event)
.each("end", function(){
svg.on("wheel.zoom", _wheelZoomEvent);
});
There is another transition inside reset() function, and we need to attach event back on there as well.
Upvotes: 1