在d3中制作按钮激活的动画游览

时间:2014-12-29 02:23:44

标签: d3.js geo cartodb

我试图通过美国东北部的三个点进行按钮激活的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>

1 个答案:

答案 0 :(得分:0)

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

您遇到的另一个问题是,使用canvas时,函数调用是不同的。您正在使用正常的svg函数调用来附加SVG,绑定数据,然后对其进行样式设置。使用canvas,您可以通过canvas context object与元素进行互动。这与您尝试在代码中使用的标准SVG对象具有不同的语法和用法。如果您关注this tutorial,您会注意到她没有调用任何SVG功能,而是使用context API来绘制canvas元素的样式。请务必查看the working example of the code

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

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,只需显示地图然后应用缩放功能即可。它可能会让你的生活变得更容易,最终迭代地构建你想要的可视化。

有关使用D3的canvassvg之间差异的更多信息,包括对每个操作执行相同操作的示例,请检查此blogpost并祝好项目。