D3缩放和平移不适用于整个地图,只适用于投影

D3 Zooming and Pan not working for entire map, just the projection

本文关键字:适用于 地图 投影 D3 不适用 缩放      更新时间:2023-09-26

希望这是一个合适的地方。这是我第一次在d3工作,我正在mercator投影世界地图上追踪一些跨越纬度(.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());
}

此处为完整代码。