【发布时间】:2013-11-08 17:19:48
【问题描述】:
我们改编了 Mike Bostock 的原始 D3 + Leaflet 示例: http://bost.ocks.org/mike/leaflet/ 这样它就不会在 Leaflet 中每次缩放时重绘所有路径。
我们的代码在这里:https://github.com/madeincluj/Leaflet.D3/blob/master/js/leaflet.d3.js
具体来说,从地理坐标到像素的投影发生在这里: https://github.com/madeincluj/Leaflet.D3/blob/master/js/leaflet.d3.js#L30-L35
我们在第一次加载时绘制 SVG 路径,然后简单地缩放/平移 SVG 以匹配地图。
这很好用,除了一个问题:D3 的路径重采样,在第一个缩放级别看起来很棒,但一旦开始放大,看起来就会越来越破碎。
有没有办法禁用重采样?
至于我们为什么要这样做:我们想要绘制很多形状(数千个)并且在每次缩放时都重新绘制它们是不切实际的。
编辑 经过一番挖掘,似乎这里发生了重采样:
function d3_geo_pathProjectStream(project) {
var resample = d3_geo_resample(function(x, y) {
return project([ x * d3_degrees, y * d3_degrees ]);
});
return function(stream) {
return d3_geo_projectionRadians(resample(stream));
};
}
有没有办法跳过重采样步骤?
编辑 2
什么是红鲱鱼!我们在向d3.geo.path().projection 和d3.geo.transform 对象发送原始函数之间来回切换,但无济于事。
但实际上问题在于传单的latLngToLayerPoint,它(显然!)将 point.x 和 point.y 舍入为整数。这意味着当您初始化 SVG 渲染时,您越缩小,您损失的精度就越高。
解决方案是使用这样的自定义函数:
function latLngToPoint(latlng) {
return map.project(latlng)._subtract(map.getPixelOrigin());
};
var t = d3.geo.transform({
point: function(x, y) {
var point = latLngToPoint(new L.LatLng(y, x));
return this.stream.point(point.x, point.y);
}
});
this.path = d3.geo.path().projection(t);
类似于leaflet 自己的latLngToLayerPoint,但没有四舍五入。 (注意map.getPixelOrigin() 也是四舍五入的,所以你可能需要重写它)
你每天都会学到一些东西,不是吗。
【问题讨论】:
-
你必须修改源代码。
-
您是否尝试过简单地将返回更改为
return d3_geo_projectionRadians(stream));,而忽略重新采样? -
嗨,拉尔斯,睡个好觉真的很神奇!问题出在我的传单部分(见编辑 2)
标签: javascript svg d3.js leaflet