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.