After reading variable scope in d3 javascript I assumed that in general you should place all your functions within the d3.json() {}
request.
I am working with some map zooming code from http://techslides.com/demos/d3/us-zoom-county.html and am trying to figure out why the clicked(d)
function is outside of the d3.json
request.
Additionally, why won't the code work with the clicked(d)
function inside the d3.json
request?
var width = 960,
height = 500,
centered;
var projection = d3.geo.albersUsa()
.scale(1070)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
d3.json("data/us.json", function(error, us) {
g.append("g")
.attr("id", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("d", path)
.attr("class", "county-boundary")
.on("click", countyclicked);
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.attr("class", "state")
.on("click", clicked);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("id", "state-borders")
.attr("d", path);
});
function clicked(d) {
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 4;
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
g.selectAll("path")
.classed("active", centered && function(d) { return d === centered; });
g.transition()
.duration(750)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
.style("stroke-width", 1.5 / k + "px");
}
function countyclicked(d) {
alert(d.id);
}
I am trying to figure out why the
clicked(d)
function is outside of thed3.json
request.
Where a function is defined is mostly irrelevant, it just needs to be accessible from where it should be referenced. clicked
is accessible inside the d3.json
callback, so that's fine.
The location of the function is only important if it is supposed to be a closure , ie needs access to values that are not passed as arguments. Eg if clicked
needed to access us
directly, it would have to be defined inside the callback.
That's not the case here though, clicked
gets all the data it needs via its parameter.
However, what is important here is that the function is only being called after the data was received, since it is bound as event handler inside the callback ( .on("click", clicked)
) based on the data that was received.
why won't the code work with the
clicked(d)
function inside thed3.json
request?
I don't see any reason why that would be the case.
That's because the function is also bound outside the callback to the container here:
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
If you move inside the callback it is not accessible outside to that code anymore.
Note that clicked
itself checks whether data is available or not by checking whether the argument d
is set or not.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.