我们改编了 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);
它类似于传单自己的latLngToLayerPoint
,但没有四舍五入。(注意它map.getPixelOrigin()
也是四舍五入的,所以可能你需要重写它)
你每天都会学到一些东西,不是吗。