json - d3.js svg 从 (geo/topo)json 绘制轮廓线

标签 json svg d3.js geojson topojson

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

这是我想要创建的图像: Example of final product. (Note: the colors are not true to the contours in the example, this is just from photoshop)

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

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

我试图阐明执行此操作的最佳方法,并找出我对 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>

因此,除了让其在基本级别上呈现之外,其他问题是: 我是否能够选择单独的线条来设置动画,例如使用描边-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");
    });

但是我无法获得我需要的效果(绘制线条)。它们似乎从小破折号中淡入,而不是绘制整个破折号。我可以在浏览器中看到,笔画破折号数组和偏移量已正确分配,只是无法弄清楚为什么不遵守转换。

最佳答案

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

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

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

一旦您的可视化工作正常,您将能够创建各种交互等。例如,在我的示例中,您可以使用如下所示的方法突出显示鼠标悬停事件上的轮廓:

.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));
        })
}

希望这能让你继续前进

关于json - d3.js svg 从 (geo/topo)json 绘制轮廓线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22876086/

相关文章:

javascript - SVG绘制两个矩形之间的连接线

javascript - d3 库 - 如何设置图例值

events - d3.js - 转换中断事件?

javascript - SVG 操纵渐变填充颜色

javascript - 从 asp.net 中的代码隐藏文件获取 json 到 javascript

javascript - 使用 meteor session 返回将循环结构转换为 JSON 的注入(inject)脚本

python - 如何使用 scrapy 将多个页面的数据收集到单个数据结构中

html - 使用父容器缩放 SVG

javascript - 使用 PHP 从 JSON 检索数组

javascript - 使用 svg 格式的 D3.js 预渲染饼图服务器时出错