JSAPIThree 数据源系统学习笔记:让数据在地图上可视化

作为一个刚开始学习 mapvthree 的小白,今天要学习数据源系统了!听说这个系统可以把各种格式的数据加载到地图上,还能让数据可视化!想想就实用!

第一次听说数据源系统

今天在文档里看到了"数据源"这个词,一开始我还以为是数据库,结果查了一下才知道,原来这是用来存储和加载地理数据的系统!

文档说数据源系统可以:

  • 存储带坐标信息的数据
  • 支持多种数据格式(GeoJSON、JSON、CSV)
  • 与可视化组件配合使用
  • 动态添加、删除、修改数据

我的理解:简单说就是"数据仓库",把地理数据存起来,然后给可视化组件用!

第一步:理解数据源的基本概念

作为一个初学者,我习惯先理解基本概念。文档说 DataSource 是数据源类,用于存储一组带坐标信息的数据。

我的发现:数据源通常与可视化组件配合使用:

js 复制代码
// 创建可视化组件
const point = engine.add(new mapvthree.SimplePoint());

// 创建数据源
const dataSource = new mapvthree.DataSource();

// 将数据源赋值给可视化组件
point.dataSource = dataSource;

我的理解:数据源存储数据,可视化组件负责渲染,两者配合才能显示数据!

DataItem:数据的最小单元

文档说 DataItem 是数据的最小单元,用于存储单条数据的信息。

js 复制代码
// 创建一个点数据
const dataItem = new mapvthree.DataItem([116.404, 39.915, 10]);

// 添加到数据源
dataSource.add(dataItem);

我的理解

  • DataItem 是单条数据
  • DataSource 是数据集合
  • 一个数据源可以包含多个 DataItem

第二步:使用 GeoJSON 数据源

看到基本概念后,我想:怎么加载实际的数据?

文档说可以用 GeoJSONDataSource 来加载 GeoJSON 格式的数据!

js 复制代码
import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {
    map: {
        center: [116.404, 39.915],
        range: 2000,
    },
});

// 创建点图层
const point = engine.add(new mapvthree.SimplePoint({
    size: 15,
}));

// 从 URL 加载 GeoJSON 数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
point.dataSource = dataSource;

我的发现fromURL 是异步方法,需要用 await 等待数据加载完成!

我的理解

  • fromURL:从 URL 加载数据
  • fromGeoJSON:直接传入 GeoJSON 对象

我的尝试

js 复制代码
// 方式 1:从 URL 加载
const dataSource1 = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');

// 方式 2:直接传入 GeoJSON 对象
const geojson = {
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [116.404, 39.915],
            },
            properties: {},
        },
    ],
};
const dataSource2 = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);

我的发现:两种方式都可以,根据数据来源选择合适的方式!

第三步:使用 JSON 数据源

看到 GeoJSON 后,我想:如果数据是 JSON 格式怎么办?

文档说可以用 JSONDataSource 来加载 JSON 格式的数据!

js 复制代码
// 从 URL 加载 JSON 数据
const dataSource = await mapvthree.JSONDataSource.fromURL('data/json/points.json');
point.dataSource = dataSource;

我的理解:JSON 数据源需要满足特定格式:

  1. 有坐标字段(默认是 coordinates,可通过 coordinatesKey 指定)
  2. 坐标数据满足 WKT 格式要求

我的尝试

js 复制代码
// JSON 数据格式示例
const jsonData = [{
    coordinates: 'POINT(116.404 39.915)',
    name: '北京',
}, {
    coordinates: 'POINT(121.473 31.230)',
    name: '上海',
}];

const dataSource = mapvthree.JSONDataSource.fromJSON(jsonData);
point.dataSource = dataSource;

我的发现:JSON 数据源支持 WKT 格式的坐标!

自定义坐标解析

如果坐标不是 WKT 格式,可以自定义解析函数:

js 复制代码
const dataSource = mapvthree.JSONDataSource.fromJSON([{
    position: [116.404, 39.915],
    color: 0xff0000,
}, {
    position: '121.473, 31.230',
    color: 0x00ff00,
}], {
    coordinatesKey: 'position', // 指定坐标字段
    parseCoordinates: function({position}) {
        // 自定义解析函数
        if (Array.isArray(position)) {
            return position;
        } else {
            return position.split(',').map(v => parseFloat(v));
        }
    },
});

我的发现:可以自定义解析函数,处理各种格式的坐标数据!

第四步:使用 CSV 数据源

看到 JSON 后,我想:如果数据是 CSV 格式怎么办?

文档说可以用 CSVDataSource 来加载 CSV 格式的数据!

js 复制代码
// 从 URL 加载 CSV 数据
const dataSource = await mapvthree.CSVDataSource.fromURL('data/csv/points.csv');
point.dataSource = dataSource;

我的理解:CSV 数据源也需要满足特定格式:

  1. 有坐标列(默认是 coordinates,可通过 coordinatesKey 指定)
  2. 坐标数据满足 WKT 格式要求

我的发现:CSV 数据源和 JSON 数据源的格式要求类似,都支持 WKT 格式!

第五步:定义数据属性

看到可以加载数据后,我想:能不能根据数据的不同属性显示不同的样式?

文档说可以用 defineAttribute 来定义数据属性!

js 复制代码
// 加载数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');

// 定义颜色属性
dataSource.defineAttribute('color', 'color');

// 定义大小属性
dataSource.defineAttribute('size', 'size');

我的理解defineAttribute 可以将数据中的字段映射到可视化属性!

我的尝试

js 复制代码
// 创建支持颜色和大小的点图层
const point = engine.add(new mapvthree.SimplePoint({
    vertexColors: true, // 开启颜色属性
    vertexSizes: true,  // 开启大小属性
}));

// 加载数据并定义属性
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
dataSource.defineAttribute('color', 'color');
dataSource.defineAttribute('size', 'size');

point.dataSource = dataSource;

我的发现 :需要在可视化组件中开启对应的属性标志(如 vertexColors),才能使用数据属性!

使用回调函数定义属性

文档说可以用回调函数来动态计算属性值:

js 复制代码
// 使用回调函数定义颜色
dataSource.defineAttribute('color', properties => {
    // 根据数据动态计算颜色
    return properties.count > 100 ? 0xff0000 : 0x00ff00;
});

// 使用回调函数定义大小
dataSource.defineAttribute('size', properties => {
    return properties.count * 2;
});

我的发现:回调函数可以灵活地根据数据计算属性值!

第六步:动态修改数据

看到可以加载数据后,我想:能不能动态添加、删除、修改数据?

文档说数据源提供了 addremovesetData 等方法来修改数据!

js 复制代码
// 添加数据
const newItem = new mapvthree.DataItem([116.404, 39.915]);
dataSource.add(newItem);

// 删除数据
dataSource.remove(itemId);

// 更新整个数据源
dataSource.setData(newGeoJSONData);

// 修改单个数据的属性
dataSource.setAttributeValues(itemId, {
    color: 0xff0000,
    size: 20,
});

// 修改单个数据的坐标
dataSource.setCoordinates(itemId, [116.414, 39.925]);

我的发现:可以动态地添加、删除、修改数据,非常灵活!

我的尝试

js 复制代码
// 点击地图添加点
engine.map.addEventListener('click', e => {
    if (!e.target) {
        const newItem = new mapvthree.DataItem(e.point);
        dataSource.add(newItem);
    }
});

// 点击点删除
point.addEventListener('rightclick', e => {
    dataSource.remove(e.entity.value.id);
});

// 点击点修改颜色
point.addEventListener('click', e => {
    dataSource.setAttributeValues(e.entity.value.id, {
        color: 0xffffff * Math.random(),
    });
});

我的发现:结合事件系统,可以实现交互式的数据编辑!

第七步:创建自定义数据源

看到可以加载各种格式的数据后,我想:能不能手动创建数据源?

文档说可以直接使用 DataSource 构造函数创建数据源!

js 复制代码
// 创建数据源
const dataSource = new mapvthree.DataSource({
    attributes: {
        color: p => p.color || 0xffff00,
        size: p => p.size || 10,
    },
});

// 创建数据项
const item1 = new mapvthree.DataItem([116.404, 39.915], {
    color: 0xff0000,
    size: 20,
});

const item2 = new mapvthree.DataItem([121.473, 31.230], {
    color: 0x00ff00,
    size: 15,
});

// 添加数据项
dataSource.add(item1);
dataSource.add(item2);

// 绑定到可视化组件
point.dataSource = dataSource;

我的发现:可以手动创建数据源和数据项,适合动态生成数据的场景!

创建不同类型的几何数据

文档说 DataItem 可以表示不同类型的几何图形:

js 复制代码
// 点数据
const pointItem = new mapvthree.DataItem([116.404, 39.915]);

// 线数据
const lineItem = new mapvthree.DataItem({
    geometry: {
        type: 'LineString',
        coordinates: [[116.404, 39.915], [121.473, 31.230]],
    },
});

// 面数据
const polygonItem = new mapvthree.DataItem({
    geometry: {
        type: 'Polygon',
        coordinates: [[[116.404, 39.915], [116.414, 39.915], [116.414, 39.925], [116.404, 39.925], [116.404, 39.915]]],
    },
});

我的发现:可以创建点、线、面等不同类型的几何数据!

第八步:设置数据投影

看到可以创建数据后,我想:如果数据的坐标系统不同怎么办?

文档说可以通过 crs 属性来设置数据的投影信息!

js 复制代码
// 创建使用投影坐标的数据项
const item = new mapvthree.DataItem({
    geometry: {
        type: 'Point',
        coordinates: [12960000, 4850000, 0], // 投影坐标
    },
}, {
    crs: 'EPSG:3857', // 指定投影
});

我的理解:引擎会自动将数据从源投影转换到目标投影!

我的发现:这样就能处理不同坐标系统的数据了!

第九步:完整示例

我想写一个完整的示例,把学到的都用上:

js 复制代码
import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

const engine = new mapvthree.Engine(container, {
    map: {
        center: [116.404, 39.915],
        range: 2000,
    },
    rendering: {
        enableAnimationLoop: true,
    },
});

// 创建支持颜色和大小的点图层
const point = engine.add(new mapvthree.SimplePoint({
    size: 15,
    vertexColors: true,
    vertexSizes: true,
}));

// 从 URL 加载 GeoJSON 数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');

// 定义属性
dataSource.defineAttribute('color', properties => {
    return properties.count > 100 ? 0xff0000 : 0x00ff00;
});
dataSource.defineAttribute('size', properties => {
    return properties.count * 2;
});

// 绑定数据源
point.dataSource = dataSource;

// 点击地图添加点
engine.map.addEventListener('click', e => {
    if (!e.target) {
        const newItem = new mapvthree.DataItem(e.point, {
            count: Math.random() * 200,
        });
        dataSource.add(newItem);
    }
});

// 点击点修改颜色
point.addEventListener('click', e => {
    dataSource.setAttributeValues(e.entity.value.id, {
        count: Math.random() * 200,
    });
});

我的感受:写一个完整的示例,把学到的都用上,感觉很有成就感!

第十步:踩过的坑

作为一个初学者,我踩了不少坑,记录下来避免再犯:

坑 1:数据源不显示

原因:数据源加载是异步的,在数据加载完成前就绑定了。

解决 :确保使用 await 等待数据加载完成后再绑定。

坑 2:属性不生效

原因:没有在可视化组件中开启对应的属性标志。

解决 :需要在组件中开启对应的属性标志,如 vertexColorsvertexSizes

坑 3:坐标格式错误

原因:坐标格式不符合要求,或者坐标字段名不对。

解决

  1. 确保坐标格式正确(WKT 格式或数组格式)
  2. 使用 coordinatesKey 指定坐标字段名

坑 4:JSON/CSV 数据解析失败

原因:坐标数据不是 WKT 格式,且没有自定义解析函数。

解决 :使用 parseCoordinates 自定义解析函数。

坑 5:数据更新不生效

原因:使用了错误的方法更新数据。

解决

  • 更新整个数据源:使用 setData
  • 添加/删除数据:使用 add/remove
  • 修改属性:使用 setAttributeValues
  • 修改坐标:使用 setCoordinates

我的学习总结

经过这一天的学习,我掌握了:

  1. 数据源的作用:存储带坐标信息的数据,与可视化组件配合使用
  2. DataItem:数据的最小单元,可以表示点、线、面等几何图形
  3. GeoJSON 数据源 :最常用的数据格式,支持 fromURLfromGeoJSON
  4. JSON 数据源:支持 WKT 格式坐标,可以自定义解析函数
  5. CSV 数据源:支持 WKT 格式坐标,格式要求与 JSON 类似
  6. 定义属性 :通过 defineAttribute 将数据字段映射到可视化属性
  7. 动态修改 :通过 addremovesetData 等方法动态修改数据
  8. 数据投影 :通过 crs 属性设置数据投影,引擎自动转换

我的感受:数据源系统真的很强大!虽然功能很多,但是用起来其实不难。关键是要理解数据源和可视化组件的关系,然后根据数据格式选择合适的加载方式!

下一步计划

  1. 学习更多数据源的配置选项
  2. 尝试处理复杂的数据格式
  3. 做一个完整的数据可视化项目

学习笔记就到这里啦!作为一个初学者,我觉得数据源系统虽然功能很多,但是用起来其实不难。关键是要理解数据源和可视化组件的关系,然后根据数据格式选择合适的加载方式!希望我的笔记能帮到其他初学者!大家一起加油!

相关推荐
霸道流氓气质1 小时前
Jquery中使用ajax传json参数并从SpringBoot后台Controller返回消息
ajax·json·jquery
阿巴~阿巴~11 小时前
JsonCpp:C++ JSON处理利器
linux·网络·c++·json·tcp·序列化和反序列化
曹牧15 小时前
Java: Json的键值双引号
java·chrome·json
最笨的羊羊15 小时前
Flink CDC系列之:Kafka JSON 序列化器JsonSerializationSchema
json·schema·flink cdc·serialization·序列化器·系列·kafkajson
东东23317 小时前
GeoJSON 介绍:Web 地图数据的通用语言
前端·javascript·json
songgz1 天前
双向流式 JSON 解析架构:并行优化大型文件处理
java·开发语言·json
星尘库1 天前
.NET Framework中报错命名空间System.Text中不存在类型或命名空间名Json
java·json·.net
Ka1Yan1 天前
快速上手MySQL中的JSON函数语法——5.x+ / 8.x+
数据库·sql·mysql·json
风华浪浪1 天前
python 基础之 jsonpatch 用于对 JSON 文档的局部更新操作
linux·python·json