Mar*_*kus 4 data-visualization geo geojson d3.js topojson
为了提高我的在线地图的性能,特别是在智能手机上,我遵循Mike Bostock的建议,在将地理数据上传到服务器之前尽可能地准备地理数据(根据他的命令行制图).例如,我正在通过d3.geoConicEqualArea()命令行投射TopoJSON数据,而不是让观看者的浏览器在加载地图时执行这项繁重的工作.
不过,我也想用类似的方法.scale,.fitSize,.fitExtent和.translate动态,这意味着我不能"烤"的规模或价值事先翻译成TopoJSON文件.
Bostock建议使用d3.geoTransform()作为预测的代理,例如,d3.geoConicEqualArea()如果您正在使用已经预测的数据但仍希望扩展或翻译它.例如,要在y轴上翻转投影,他建议:
var reflectY = d3.geoTransform({
point: function(x, y) {
this.stream.point(x, -y);
}
}),
path = d3.geoPath()
.projection(reflectY);
Run Code Online (Sandbox Code Playgroud)
我的问题:如果我使用这个D3功能,我是不是仍然强迫观众的浏览器进行大量的数据处理,这会使性能恶化?预处理数据的目的是避免这种情况.或者我是否过高估计上述d3.geoTransform()功能涉及的处理工作?
如果我使用这个D3功能,我是不是仍然强迫观众的浏览器进行大量的数据处理,这会使性能恶化?预处理数据的目的是避免这种情况.或者我是否过高估计上面d3.geoTransform()函数中涉及的处理工作?
简答:您高估了转换预测数据所需的工作量.
D3 geoProjections的球形性质
d3 geoProjection相对独特.许多平台,工具或库采用由纬度和经度对组成的点,并将它们视为在笛卡尔平面上.这在很大程度上简化了数学运算,但需要付出代价:路径遵循笛卡尔路由.
D3将经度纬度点视为它们的位置:三维椭球上的点.这在计算上花费更多,但提供了其他好处 - 例如沿着大圆路线路由路径段.
在将坐标视为3d地球上的点时,额外的计算成本d3是:
在缩放,居中等之前,先看一下简单的地理投影:
function mercator(x, y) {
return [x, Math.log(Math.tan(Math.PI / 4 + y / 2))];
}
Run Code Online (Sandbox Code Playgroud)
这可能比您上面提出的转换花费的时间更长.
在笛卡尔平面上,两个点之间的线很容易,在球体上,这很困难.沿着从东经179度到西经179度的路线 - 将这些视线放在一个很容易的笛卡尔平面上 - 在地球上划一条线.在球形地球上,线穿过反子午线.
因此,在平整路径时,沿路线需要采样,点之间的大圆距离需要弯曲,因此需要额外的点.我不确定d3中的这个过程,但肯定会发生.
笛卡尔平面上的点不需要额外采样 - 它们已经是平坦的,点之间的线是直的.没有必要检测线条是否以另一种方式缠绕在地球上.
投影后的操作
一旦投影,像.fitSize这样的东西将强制进行额外的工作,这与你使用d3.geoTransform()提出的要点基本相同:需要根据投影的位置和大小对特征进行变换和缩放.
这在自动进入特征的d3v3(之前fitSize())中非常明显:计算涉及投影特征的svg范围.
基本准科学绩效比较
使用美国的美国人口普查局shapefile,我创建了三个geojson文件:
d3.geoAlbers().fitSize([500,500],d)(文件大小为385 kb)速度的黄金标准应该是选项3,数据根据预期的显示范围进行缩放和居中,这里不需要变换,我将使用空投影来测试它
我继续使用以下方法将这些投影到500x500 svg:
// For the unprojected data
var projection = d3.geoAlbers()
.fitSize([500,500],wgs84);
var geoPath = d3.geoPath().projection(projection)
// for the projected but unscaled and uncentered data
var transform = d3.geoIdentity()
.fitSize([500,500],albers);
var projectedPath = d3.geoPath()
.projection(transform);
// for the projected, centered, and scaled data
var nullProjection = d3.geoPath()
Run Code Online (Sandbox Code Playgroud)
运行这几百次,我获得了平均渲染时间(数据被预加载):
我觉得很安全地说预先投影数据会有很大的性能提升,无论它是否实际上是居中和缩放的.
注意我使用的d3.geoIdentity()相反,d3.geoTransform()因为它允许使用fitSize(),你可以在y上反映如果需要:.reflectY(true);
| 归档时间: |
|
| 查看次数: |
384 次 |
| 最近记录: |