1

我正在尝试通过美国东北部的三个点进行按钮激活的 d3 缩放之旅,但很难让数据在视觉上显示(虽然它显示在控制台中)。我是初学者,通常可以解决问题,但这超出了我的想象。

这是一个接近我想要做的例子:

在美国不同地点之间缩放:http: //bl.ocks.org/mbostock/6242308

该示例不设置数据样式,使用 TopoJSON 并使用画布进行缩放调用。我正在尝试使用 GeoJSON 进行缩放(所以我可以链接到 CartoDB 表),并设置它的样式。

我经历了很多事情来实现这两件事,但我已经没有成功了。现在它出现空白并且一直存在。我可以实时查看数据,但无法更改样式。

我在这里做错了什么?我敢肯定这很简单,但需要轻推。


<!DOCTYPE html>
<html lang ="en">
<head>
  <meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
canvas{
color: 'blue';

}
    path.state {
      color: 'red';
    }
    </style>
</head>
<body>

<script type="text/javascript">

var width = 960,
    height = 500,
    stateMap; 

var sf = [-122.417, 37.775],
    ny = [-74.0064, 40.7142];

var scale,
    translate,
    visibleArea, // minimum area threshold for points inside viewport
    invisibleArea; // minimum area threshold for points outside viewport

var zoom = d3.behavior.zoom()
    .size([width, height])
    .on("zoom", zoomed);

var projection = d3.geo.mercator()
    .translate([width/2, height/2])
    .scale(500);

 var canvas = d3.select("body").append("canvas")
    .attr("width", width)
    .attr("height", height);

var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height);

var context = canvas.node().getContext("2d");

var path = d3.geo.path()
    .projection(simplify)
    .context(context);

stateMap = d3.json("http://linepointpath.cartodb.com/api/v2/sql?format=GeoJSON&q=SELECT * FROM GRAPHstates", function(error, stateMap) {
  console.log(stateMap)
  canvas
      svg.selectAll("path")
      .data(stateMap.feature)
      .enter().append("path")
      .attr("class", "state")
           .attr("d", path)
      .call(zoomTo(sf, 4).event)
    .transition()
      .duration(60 * 1000 / 89 * 2)
      .each(jump);
});

var simplify = d3.geo.transform({
  point: function(x, y, z) {
    if (z < visibleArea) return;
    x = x * scale + translate[0];
    y = y * scale + translate[1];
    if (x >= -10 && x <= width + 10 && y >= -10 && y <= height + 10 || z >= invisibleArea)     this.stream.point(x, y);
  }
});

function zoomTo(location, scale) {
  var point = projection(location);
  return zoom
      .translate([width / 2 - point[0] * scale, height / 2 - point[1] * scale])
      .scale(scale);
}

function zoomed(d) {
  translate = zoom.translate();
  scale = zoom.scale();
  visibleArea = 1 / scale / scale;
  invisibleArea = 200 * visibleArea;
  context.clearRect(0, 0, width, height);
  context.beginPath();
  path(d);
  context.stroke();
}

function jump() {
  var t = d3.select(this);
  (function repeat() {
    t = t.transition()
   .call(zoomTo(ny, 6).event)
  .transition()
    .call(zoomTo(sf, 4).event)
    .each("end", repeat);
  })();
}

</script>
</body>
</html>
4

1 回答 1

0

我怀疑更大的问题是,当您使用的示例使用的是TopoJSON时,您使用的是GeoJSON。两者之间的差异可能会导致s 的呈现方式出现问题。path

您遇到的另一个问题是,使用 acanvas时,函数调用是不同的。您正在使用正常的svg函数调用来附加 SVG、绑定数据并为其设置样式。使用时,您可以通过画布对象canvas与元素进行交互。这与您尝试在代码中使用的标准 SVG 对象具有不同的语法和用法。如果您遵循本教程,您会注意到她没有调用任何 SVG 函数,而是使用API 来绘制元素并设置其样式。请务必查看代码的工作示例contextcontextcanvas

在您的情况下,这意味着您的代码在这里:

svg.selectAll("path")
  .data(stateMap.feature)
  .enter().append("path")
  .attr("class", "state")
       .attr("d", path)
  .call(zoomTo(sf, 4).event)
.transition()
  .duration(60 * 1000 / 89 * 2)

是不必要的,不为你做任何事情。生成路径的代码使用对象嵌入到zoomed()函数中context

context.clearRect(0, 0, width, height);
context.beginPath();
path(d);
context.stroke();

它使用context函数来创建您要显示的对象。有一个函数调用链会产生这种行为,您需要分解该链以确保您在每一步都得到您想要的。

如果您想使用 GeoJSON,首先要显示地图,然后应用缩放功能。最终迭代地构建你想要的可视化可能会让你的生活变得更轻松。

canvas有关 D3和D3之间差异的更多信息svg,包括对每个 D3 执行相同操作的示例,请查看此博文并祝项目好运。

于 2014-12-30T15:01:42.417 回答