背景
经纬度数据有 上千万个点,这上千万数据需要通过后端传递到前端。
数据存储
后端将数据存储在OSS上。
前端通过OSS拉去数据,以TypedArray格式存储在前端内存。
TypedArray 在大数据量的存储中可以占用更少的内存,对 GC 友好等特性也可以大幅度提升可视化应用的性能。
数据存储在OSS上的形式
一个坐标点 分为 经度和纬度 两个浮点数,将这两个浮点数扩大10的7次方倍 后省略小数位,然后我们需要找一个合适二进制数据缓存区的类型数组对象(这里以JavaScript的术语说明)进行存放。
| 数据类型 | 表示范围 |
|---|---|
| 经纬度坐标(扩大10^7后) | -180*10^7 ~ 180*10^7(东西半球的坐标范围是-180到180, 南北半球的坐标范围是-90到90。) |
| 32位二进制带符号整数 | -2^31 ~ (2^31)-1 |
可以看出 32位二进制带符号整数表示范围 正好覆盖 经纬度坐标(扩大10^7后)。
生成数据文件
以实际数据举例
经度:1.21231, 纬度:2.32131 ===》1212310023213100 ====》00B8FBDC0162342C(二进制太长,这里以16进制表示)
生成的数据文件为:查看文章底部附件
代码生成方式 NodeJS方式为例
/**
* 将经纬度坐标写入二进制数据缓冲区
* @param latLons 需要写入的经纬度坐标,格式为[[lat, lon], [lat, lon]...]
* @returns {Buffer}
*/
function getBuffByLatlon(latLons = []) {
// 创建buffer缓冲区 http://nodejs.cn/api/buffer.html#buffer_buffer
// [[lat, lon], [lat, lon]] 故缓冲区的大小为 参数数组长度 * 2 * 4(由于每个经纬度占4个字节)
const buff = Buffer.allocUnsafe(latLons.length * 2 * 4)
// 当前为缓存区第几个字节
let startIndex = 0
latLons.forEach((latLon) => {
const lat = latLon[0]
const lon = latLon[1]
// 指定使用 小端序(首位表示符号位)http://nodejs.cn/api/buffer.html#buffer_buf_writeint32be_value_offset
buff.writeInt32LE(lat * 1e7, startIndex)
startIndex += 4
buff.writeInt32LE(lon * 1e7, startIndex)
startIndex += 4
})
return buff
}
/**
* 创建数据文件
*/
function creatFile() {
const fs = require('fs')
const buf = getBuffByLatlon([[1.21231, 2.32131]])
fs.writeFile('./buffFile.txt', buf, (err) => {
if (err) throw err
console.log('文件已被保存')
})
}
// 开始创建
creatFile()
注意: 这里字节序要使用 小端序,x86 体系的计算机都采用小端字节序,目前,所有个人电脑几乎都是小端字节序,所以 TypedArray 数组内部也采用小端字节序读写数据,或者更准确的说,按照本机操作系统设定的字节序读写数据。 Arraybuffer-字节序
前端获取数据文件
function fetchData() {
// OSS数据地址
var dataURL = 'xxxxxx';
var xhr = new XMLHttpRequest();
xhr.open('GET', dataURL, true);
// 设置响应数据格式为 [二进制数据缓存区]
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
// 将获取到的二进制字节流 创建为 32位二进制带符号整数
var rawData = new Int32Array(this.response);
// 用32位IEEE浮点数 存储经纬度
var data = new Float32Array(rawData.length);
for (var i = 0; i < rawData.length; i += 2) {
data[i] = rawData[i+1] / 1e7;
data[i+1] = rawData[i] / 1e7;
}
// 使用echarts渲染界面
myChart.appendData({
seriesIndex: 0,
data: data
});
}
xhr.send();
}
本地查看数据文件
推荐使用iHex(简洁方便)进行查看。