D3 缩放和平移不适用于整个地图,仅适用于投影
D3 Zooming and Pan not working for entire map, just the projection
希望这是正确的地方。这是我第一次在 d3 中工作,我正在世界墨卡托投影地图上跟踪一些跨越纬度 (.bars) 的路径。
虽然我离这张地图想去的地方还很远(试图随着时间的推移制作动画变化,然后将工具提示添加到 .bars):我受困于缩放功能。我已经让它在缩放时改变投影的比例,但它对我的矩形形状 (.bars) 没有影响。有人可以看一下,让我知道发生了什么事吗?为什么矩形在缩放时不缩放?我在缩放功能中是否没有正确访问它们?
var width = 960,
height = 550,
scale0 = (width - 1) / 2 / Math.PI;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
// .append("g");
var g = svg.append("g");
var bars = svg.append("rect");
var zoom = d3.behavior.zoom()
.translate([width / 2, height / 2])
.scale(scale0)
.scaleExtent([scale0, 8 * scale0])
.on("zoom", zoomed);
var color = d3.scale.quantize() // Takes data value inputs and will return colors
.range(['rgb(215,48,39)','rgb(244,109,67)','rgb(253,174,97)','rgb(254,224,144)','rgb(255,255,191)','rgb(224,243,248)','rgb(171,217,233)','rgb(116,173,209)','rgb(69,117,180)']);
var projection = d3.geo.mercator()
.scale((width + 1) / 2 / Math.PI)
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
svg
.call(zoom)
.call(zoom.event);
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
g.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
g.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
d3.csv("data/apr_dove.csv", function(data) {
// Returns value based on min/max of data set to Colorbrewer colors
color.domain([
d3.max(data, function(d) { return d.average_revisit; }),
d3.min(data, function(d) { return d.average_revisit; })
]);
// Defining the rectangle's attributes by monthly data of satellites (latitude and average revisit_rate)
g.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("width", width)
.attr("class", "bars")
.attr("height", function(d) {
// console.log(projection.translate([0, 0.5])[1])
return projection([0, d.latitude - 0.5])[1] - projection([0, d.latitude])[1];
})
.attr("opacity", .6)
.style("fill", function(d) {
//Get data value
var value = d.average_revisit;
if (value) {
//If value exists…
return color(value);
} else {
//If value is undefined…
return "#ccc";
}
})
//Define position of each rectangle by it's latitude from the data
.attr("transform", function(d) {
return "translate(" + projection([-180, d.latitude]) + ")"
})
.attr("d", path);
});
});
function zoomed() {
projection
.translate(zoom.translate())
.scale(zoom.scale());
svg.selectAll("*")
.attr("d", path);
}
d3.select(self.frameElement).style("height", height + "px");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://gist.github.com/sadbumblebee/64581d15b89b361a17a85e8f37172673.js"></script>
<script src="https://gist.github.com/sadbumblebee/359fc826e4e55c8c3dcb3d279783e910.js"></script>
获得适当宽度的一个想法是根据您的土地路径的大小:
var land;
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
land = g.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
....
function getLandWidth() {
return land ? land.node().getBBox().width : 0;
}
...
function zoomed() {
projection
.translate(zoom.translate())
.scale(zoom.scale());
svg.selectAll("path")
.attr("d", path);
g.selectAll(".bars")
.attr("height", function(d) {
return projection([0, d.latitude - 0.5])[1] - projection([0, d.latitude])[1];
})
.attr("transform", function(d) {
return "translate(" + projection([-180, d.latitude]) + ")"
})
.attr("width", getLandWidth());
}
完整代码here.
希望这是正确的地方。这是我第一次在 d3 中工作,我正在世界墨卡托投影地图上跟踪一些跨越纬度 (.bars) 的路径。
虽然我离这张地图想去的地方还很远(试图随着时间的推移制作动画变化,然后将工具提示添加到 .bars):我受困于缩放功能。我已经让它在缩放时改变投影的比例,但它对我的矩形形状 (.bars) 没有影响。有人可以看一下,让我知道发生了什么事吗?为什么矩形在缩放时不缩放?我在缩放功能中是否没有正确访问它们?
var width = 960,
height = 550,
scale0 = (width - 1) / 2 / Math.PI;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
// .append("g");
var g = svg.append("g");
var bars = svg.append("rect");
var zoom = d3.behavior.zoom()
.translate([width / 2, height / 2])
.scale(scale0)
.scaleExtent([scale0, 8 * scale0])
.on("zoom", zoomed);
var color = d3.scale.quantize() // Takes data value inputs and will return colors
.range(['rgb(215,48,39)','rgb(244,109,67)','rgb(253,174,97)','rgb(254,224,144)','rgb(255,255,191)','rgb(224,243,248)','rgb(171,217,233)','rgb(116,173,209)','rgb(69,117,180)']);
var projection = d3.geo.mercator()
.scale((width + 1) / 2 / Math.PI)
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
svg
.call(zoom)
.call(zoom.event);
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
g.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
g.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
d3.csv("data/apr_dove.csv", function(data) {
// Returns value based on min/max of data set to Colorbrewer colors
color.domain([
d3.max(data, function(d) { return d.average_revisit; }),
d3.min(data, function(d) { return d.average_revisit; })
]);
// Defining the rectangle's attributes by monthly data of satellites (latitude and average revisit_rate)
g.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("width", width)
.attr("class", "bars")
.attr("height", function(d) {
// console.log(projection.translate([0, 0.5])[1])
return projection([0, d.latitude - 0.5])[1] - projection([0, d.latitude])[1];
})
.attr("opacity", .6)
.style("fill", function(d) {
//Get data value
var value = d.average_revisit;
if (value) {
//If value exists…
return color(value);
} else {
//If value is undefined…
return "#ccc";
}
})
//Define position of each rectangle by it's latitude from the data
.attr("transform", function(d) {
return "translate(" + projection([-180, d.latitude]) + ")"
})
.attr("d", path);
});
});
function zoomed() {
projection
.translate(zoom.translate())
.scale(zoom.scale());
svg.selectAll("*")
.attr("d", path);
}
d3.select(self.frameElement).style("height", height + "px");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://gist.github.com/sadbumblebee/64581d15b89b361a17a85e8f37172673.js"></script>
<script src="https://gist.github.com/sadbumblebee/359fc826e4e55c8c3dcb3d279783e910.js"></script>
获得适当宽度的一个想法是根据您的土地路径的大小:
var land;
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
land = g.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
....
function getLandWidth() {
return land ? land.node().getBBox().width : 0;
}
...
function zoomed() {
projection
.translate(zoom.translate())
.scale(zoom.scale());
svg.selectAll("path")
.attr("d", path);
g.selectAll(".bars")
.attr("height", function(d) {
return projection([0, d.latitude - 0.5])[1] - projection([0, d.latitude])[1];
})
.attr("transform", function(d) {
return "translate(" + projection([-180, d.latitude]) + ")"
})
.attr("width", getLandWidth());
}
完整代码here.