需求背景
厂商提供十万多个点位,及数据侧提供每个点位的数值
webgis侧需要把这些海量数据,做成栅格,并生成颜色等值图加入地图中
需要考虑的点:
1.十万级别数据,加入地图的性能问题(开始的10多秒 -> 毫秒级别
)
2.栅格颜色色块之间是否要做颜色融合
3.厂商所提供的点位的坐标系是否相同,投影坐标系的区别(二维地图因为坐标系多,存在投影坐标系偏移问题)
4.基于以上,如果需求上再加一条时间轴,需要达到十万级别数据,秒级更新,点位数据接口是否需要添加 数据池机制
解决效果
地图数据处理
处理目的:需要把十万级别的点坐标转化为一个个栅格
原点位数据
邻域分析
使用arcgis中,图像缓冲功能,可得到规则的栅格。
栅格数据
最终的到的是一个栅格的geojson
文件,期间的转换操作需要可以私信我
在qigs上添加,每个栅格中点的坐标,获取栅格中点label
的坐标位置
index.vue
拿到栅格数据后,我曾尝试三种地图加载方法(建议不要听半吊子方案)
1.使用视窗范围,去限制一次性加载栅格的数量,从而达到性能优化的效果
2.使用位图,将栅格bbox,和数值传给位图,将输出的结果,作为图片图层,达到颜色填充效果(准确性?)
以上两种方案,因为后续的坑有点多,比如不同的坐标系的偏移,计算时js的小数点丢失,地图引擎的坑…
然后都不得不,静下心来好好想一波,知道我看到这个,框架限制我们只能读取文件,然而前端怎么不可以自己创建文件
呢
// create a new blob from geojson featurecollection
const blob = new Blob([JSON.stringify(geojson)], {
type: "application/json"
});
// URL reference to the blob
const url = URL.createObjectURL(blob);
3
.最终方案:用类似 Cesium.GeoJsonDataSource.load
,达到了需求效果
const mapCtx = getGlobalMapCtx();
if (iridescentColorLayer) {
mapCtx.view.map.layers.remove(iridescentColorLayer);
mapCtx.view.map.layers.remove(iridescentgridLayer);
iridescentColorLayer = null
iridescentgridLayer = null
}
iridescentGridJson.features.forEach((item, i) => {
item.properties.colorValue = formatToFixed(model.iridescentData[model.curTime][i], 0)
})
const blob = new Blob([JSON.stringify(iridescentGridJson)], {type: "application/json"});
const url = URL.createObjectURL(blob);
const classBreaksRenderer = new ClassBreaksRenderer({
field: 'colorValue', // 替换为你的数值字段名
classBreakInfos: [
{
minValue: 0.1,
maxValue: 9.9,
symbol: {type: 'simple-fill', color: 'rgba(166, 255, 176, .4)', outline: {color: 'transparent',}}
},
{
minValue: 10,
maxValue: 25,
symbol: {type: 'simple-fill', color: 'rgba(30, 186, 37, .4)', outline: {color: 'transparent',}}
},
{
minValue: 25,
maxValue: 50,
symbol: {type: 'simple-fill', color: 'rgba(95, 207, 255, .4)', outline: {color: 'transparent'}}
},
{
minValue: 50,
maxValue: 100,
symbol: {type: 'simple-fill', color: 'rgba(0, 0, 255, .4)', outline: {color: 'transparent',}}
},
{
minValue: 100,
maxValue: 250,
symbol: {type: 'simple-fill', color: 'rgba(249, 0, 241, .4)', outline: {color: 'transparent',}}
},
{
minValue: 250,
maxValue: 50000,
symbol: {type: 'simple-fill', color: 'rgba(255, 0, 0, .4)', outline: {color: 'transparent',}}
},
]
});
iridescentColorLayer = new GeoJSONLayer({
url,
renderer: classBreaksRenderer,
spatialReference: {wkid: 4326},
z: 1000
});
mapCtx.view.map.layers.add(iridescentColorLayer);
iridescentgridLayer = new GeoJSONLayer({
url,
renderer: {
type: 'simple',
symbol: {
type: 'simple-fill',
color: 'transparent',
outline: {
color: '#fff',
width: 1
}
}
},
labelingInfo: [
new LabelClass({
labelExpressionInfo: {expression: "$feature.colorValue"}, // 替换为你的数值字段名
symbol: {
type: "text",
color: "#fff", // 标签文字颜色
haloColor: "white",
haloSize: 1,
font: {
size: 20, // 标签文字大小
}
},
labelPlacement: "center-center" // 标签居中对齐
})
],
minScale: 50000,
spatialReference: {wkid: 4326},
visible: false,
z: 1001
});
mapCtx.view.map.layers.add(iridescentgridLayer);