【问题标题】:d3.js svg drawing contour lines from (geo/topo)jsond3.js svg 从 (geo/topo)json 绘制等高线
【发布时间】:2014-04-05 03:06:00
【问题描述】:

我正在寻找一些指导,了解如何根据来自 (geo/topo)JSON 的等高线数据创建由路径组成的 SVG 图像,并使用 d3.js 进行渲染。

这是我想要创建的图像:

最终,我希望图像能够响应式缩放、动画(绘制线条、交互式更改颜色)路径,并能够交换不同的数据文件以呈现其他图像。

我已经浏览了几个指南、教程等,但到目前为止我似乎遗漏了一些步骤或实施了错误的程序,所以我想我会在这里问。感谢您的帮助。

我正在尝试澄清执行此操作的最佳方法,并找出我在 d3.js 中的功能/程序方面的误解。

我通过在 QGIS 中提取等高线来从 DEM(数字高程模型)数据创建等高线。为了从中获取 JSON,我尝试在 QGIS 中保存为 GeoJSON,并在 OGR2OGR 中将 Shapefile (ESRI .shp) 转换为 GeoJSON。我也尝试过使用 Node 的 Topojson (https://www.npmjs.org/package/topojson)。在大多数情况下,我已经能够获取 JSON 文件,尽管我转换它们的方式可能有问题,或者来自 QGIS 的原始轮廓数据使其与我在 d3 中尝试过的不兼容.

当 JSON 被渲染时,我得到的结果基本上看起来像黑盒子(看起来像渲染不正确的多边形在 svg 容器内变得狂野)。如果我将填充颜色更改为无,我会看到到处都是疯狂的线条。我在某处读到,TopoJSON 必须是多边形而不是线或折线,因为它使用弧线,但我使用 GeoJSON 得到了相同的结果。

我想知道这是否与我从 QGIS 导出轮廓线并转换为 JSON 的方式有关,也许投影没有对齐?转换时自动创建的行中也可能存在一些错误,但我不确定如何修复这些错误。正如您在示例图像中看到的那样,我的一些轮廓不是闭环,因为它们超出了我有数据用于/想要显示的区域的边界。这些应该被渲染为折线或路径是否有意义?

另外请注意,我对这些线路的“地理空间性”并不特别感兴趣,因为它们在这个项目中的经纬度或地理位置。基本上只是使用来自真实地理数据的等高线来显示线型。

这是我的代码:

<script type="text/javascript">
var width = 500,
    height = 500;

var svg = d3.select("#section-1-svg").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("contour.json", function(error, contour) {
    console.log(contour);
});

var path = d3.geo.path()
    .projection(d3.geo.mercator());

    d3.json("contour.json", function(error, json) {

    svg.selectAll("path")
        .data(json.features)
        .enter()
        .append("path")
        .attr("d", path);
});
</script>

所以除了让这个在基本层面上呈现之外,其他问题是: 我可以选择单独的线条来制作动画,例如 stroke-dashoffset 吗? 此源 JSON 是否仍包含高程数据,以便我可以根据高程为线条着色?

感谢您帮助我走上正轨!我会很感激有人为我澄清这一点并告知我呈现它的最佳方式。

编辑:使用 user1614080 示例中的代码,我正在渲染这些行:

    svg.selectAll("path")
    .data(topo).enter()
    .append("path")
    .style("fill", "none")
    .style("stroke", function(d, i) {
        return interp(cScale(d.properties.ELEV));
    })
.attr("d", path)
.each(function(d) {
    d.totalLength = this.getTotalLength();
    console.log(d.totalLength);

})
.attr("stroke-dasharray", function(d) { return d.totalLength + " " + d.totalLength;})
.attr("stroke-dashoffset", function(d) { return d.totalLength; })
.transition()
    .delay(function(d, i) { return i * 200; })
    .duration(4000)
    .ease("linear")
    .attr("stroke-dashoffset", "0");
    });

但我无法获得我需要的效果(画线)。它们似乎从小破折号淡入,而不是绘制整个破折号。我可以在浏览器中看到 stroke-dasharray 和 offset 被正确分配,只是无法弄清楚为什么不尊重过渡。

【问题讨论】:

  • 如果没有看到完整的示例,我真的不知道发生了什么,但this vis I made a while ago 可能会对您有所帮助。我使用了基本相同的工作流程——DEM 通过 QGIS 到 GeoJSON,然后使用 D3 加载和处理。

标签: json svg d3.js geojson topojson


【解决方案1】:

从 Lar 提到的内容来看,我真的看不出你所拥有的有什么问题(除了你是两个相同的 d3.json 调用,但这不应该给你带来问题)。

您描述的工作流程与我之前所做的或多或少相同。我能想到的唯一可能给您带来麻烦的事情(尽管不是在您提供的代码中)是 topojson 的默认值不保留功能属性,您必须使用 -p 开关。

无论如何,我一直想做一个轮廓示例,这似乎是一个很好的机会,所以我创建了一个您可以看到 here 的示例。代码和自述文件中有相当多的解释,所以我希望这对您有所帮助。

一旦你的 vis 正常工作,你就可以创建各种交互等。例如,在我的示例中,你可以使用以下内容突出显示鼠标悬停事件的轮廓:

.on("mouseover", highlight)
.on("mouseout", unhighlight(this, d)

function highlight(x) {
    var s = d3.select(this);
    s.style("stroke", "red");
}

function unhighlight(x,y) {
    var old = y.properties.ELEV;
    var u = d3.select(x);
    u.style("stroke", function(d, i) {
            return interp(cScale(old));
        })
}

希望这能让你继续前进

【讨论】:

  • 这非常有帮助!看起来我遇到的主要问题来自于 QGIS 中数据的来源/轮廓的创建,这导致数据的几何形状无效。我将尝试重新处理数据(来自 DEM),看看我是否能做到这一点。
  • 使用 QGIS,您需要检查投影,如果您在 d3 中使用墨卡托投影,请在 QGIS 中使用 WSG84
  • 我能够整理出源数据...我不得不将投影更改为 '84 并且还使用 QGIS 中的 Clip 功能在转换为 topoJSON 之前消除了许多无效几何图形(不要'不要忘记 -p 标志)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 2017-09-03
  • 2018-04-24
  • 2023-04-04
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
相关资源
最近更新 更多