我正在寻找关于如何根据来自(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,只是无法弄清楚为什么不遵循转换。
答案 0 :(得分:3)
继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));
})
}
希望这能让你前进