我尝试使用EXISTS(SELECT 1 FROM t_file WHERE f.f_revisionId = r.id AND f.filename LIKE '%src%')
和D3.js
呈现瑞士地图。可以找到基础JSON here。首先,我尝试关注this tutorial,在我无法像地图一样远距离渲染任何内容之后,我发现this question on here带有指向工作示例的链接。我从那里开始使用这个代码,我目前正在使用:
TopoJSON
由于<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<style>
path {
fill: #ccc;
}
</style>
</head>
<body>
<h1>topojson simplified Switzerland</h1>
<script>
var width = window.innerWidth,
height = window.innerHeight;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var projection = d3.geo.mercator()
.scale(500)
.translate([-900, 0]);
var path = d3.geo.path()
.projection(projection);
d3.json("ch-cantons.json", function(error, topology) {
if (error) throw error;
svg.selectAll("path")
.data(topojson.feature(topology, topology.objects.cantons).features).enter().append("path").attr("d", path);
});
</script>
</body>
</html>
看起来没问题(在一些在复制/粘贴后正确呈现它的在线平台上检查)并且只有很少的代码可能出错,我认为错误在投影参数中。摆弄一点也无法使其发挥作用。所以任何帮助都将非常感谢!
答案 0 :(得分:1)
你是对的,错误在投影中。 但是,错误取决于您的数据是投影还是未投影(长对)。
如果你有WGS84中的数据 - 也就是说lat long pair,那么你有这个问题:
使用您的投影,但只改变数据源我得到类似的东西(我在右边的空海中刮掉了):
要正确居中墨卡托,您需要知道您感兴趣的区域的中心坐标。这通常可以相当普遍,对瑞士我可能会尝试47N 8.25E。
一旦你有这个坐标,你需要把它放在中间。一种方法是在x轴上旋转并以y:
为中心var projection = d3.geo.mercator()
.scale(3500)
.rotate([-8.25,0])
.center([0,47])
.translate([width/2,height/2])
请注意,x旋转为负,您正在投影下旋转地球。
另一种选择是在x和y上旋转,这可能是接近极点时的首选选项 - 因为墨卡托变形在高纬度变得不可行。这种方法看起来像:
var projection = d3.geo.mercator()
.scale(4000)
.rotate([-8.25,-47])
.center([0,0])
.translate([width/2,height/2])
再次注意负旋转值。第二种选择需要更高的比例值,因为这种方法基本上将瑞士视为零,在墨卡托投影上为零 - 沿着赤道的土地面积最小化。
所以你必须稍微调整一下比例,但是现在你应该能够看到你的数据了(假设你的数据是正确的lat长对)。
根据下面的评论,其中包含一个链接的json文件,我们可以看到这是你的问题。
有两种可能的解决方案:
选项一是最简单的,你将取消数据的投影 - 这需要知道当前的投影。在GIS软件中,这通常会将其投影为WGS84,可以说它不是真正的投影而是基准。获得lat long对后,您可以按照上述步骤查看未投影的数据。
选项二完全跳过d3.geoProjection。相反,我们将创建一个转换函数,将投影坐标转换为所需的SVG坐标。
地理投影看起来像:
function scale (scaleFactor) {
return d3.geo.transform({
point: function(x, y) {
this.stream.point(x * scaleFactor, (y * scaleFactor);
}
});
}
用作投影:
var path = d3.geo.path().projection(scale(0.1));
它只需要一个已经是笛卡尔坐标的x,y坐标流,并以指定的方式对它们进行转换。
要翻译地图以使其居中,您需要知道中心坐标。您可以使用path.bounds
:
var bounds = path.bounds(features);
var centerX = (bounds[0][0] + bounds[1][0])/2;
var centerY = (bounds[0][1] + bounds[1][1])/2;
Path.bounds返回要素的左上角和右下角。这是关键部分,你可以做一个自动缩放功能,那里有很多例子,但我喜欢经常手动缩放。如果地图居中,这很容易。对于您的地图,您的geoTransform可能如下所示:
function scale (scaleFactor,cx,cy,width,height) {
return d3.geo.transform({
point: function(x, y) {
this.stream.point((x-cx) * scaleFactor + width/2, (y-cy) * scaleFactor +height/2);
}
});
}
此处cx
和cy
指的是要素的中间,宽度和高度指的是svg元素的宽度和高度 - 我们不希望在SVG点聚集的要素[0 ,0]。
总而言之,这给了我们类似的东西(比例因子为0.002):
这是一个更新的JSbin:http://jsbin.com/wolamuzeze/edit?html,output
请记住,比例取决于窗口大小,因为您的宽度/高度与窗口大小相关。这可能最好通过自动设置缩放级别来解决,但如果您有标签(例如),这可能会产生问题。
这个答案也许有帮助:Scaling d3 v4 map to fit SVG (or at all)