作為一個剛開始學習 mapvthree 的小白,今天要學習數據源系統了!聽説這個系統可以把各種格式的數據加載到地圖上,還能讓數據可視化!想想就實用!
第一次聽説數據源系統
今天在文檔裏看到了"數據源"這個詞,一開始我還以為是數據庫,結果查了一下才知道,原來這是用來存儲和加載地理數據的系統!
文檔説數據源系統可以:
- 存儲帶座標信息的數據
- 支持多種數據格式(GeoJSON、JSON、CSV)
- 與可視化組件配合使用
- 動態添加、刪除、修改數據
我的理解:簡單説就是"數據倉庫",把地理數據存起來,然後給可視化組件用!
第一步:理解數據源的基本概念
作為一個初學者,我習慣先理解基本概念。文檔説 DataSource 是數據源類,用於存儲一組帶座標信息的數據。
我的發現:數據源通常與可視化組件配合使用:
// 創建可視化組件
const point = engine.add(new mapvthree.SimplePoint());
// 創建數據源
const dataSource = new mapvthree.DataSource();
// 將數據源賦值給可視化組件
point.dataSource = dataSource;
我的理解:數據源存儲數據,可視化組件負責渲染,兩者配合才能顯示數據!
DataItem:數據的最小單元
文檔説 DataItem 是數據的最小單元,用於存儲單條數據的信息。
// 創建一個點數據
const dataItem = new mapvthree.DataItem([116.404, 39.915, 10]);
// 添加到數據源
dataSource.add(dataItem);
我的理解:
DataItem是單條數據DataSource是數據集合- 一個數據源可以包含多個
DataItem
第二步:使用 GeoJSON 數據源
看到基本概念後,我想:怎麼加載實際的數據?
文檔説可以用 GeoJSONDataSource 來加載 GeoJSON 格式的數據!
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 對象
我的嘗試:
// 方式 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 格式的數據!
// 從 URL 加載 JSON 數據
const dataSource = await mapvthree.JSONDataSource.fromURL('data/json/points.json');
point.dataSource = dataSource;
我的理解:JSON 數據源需要滿足特定格式:
- 有座標字段(默認是
coordinates,可通過coordinatesKey指定) - 座標數據滿足 WKT 格式要求
我的嘗試:
// 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 格式,可以自定義解析函數:
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 格式的數據!
// 從 URL 加載 CSV 數據
const dataSource = await mapvthree.CSVDataSource.fromURL('data/csv/points.csv');
point.dataSource = dataSource;
我的理解:CSV 數據源也需要滿足特定格式:
- 有座標列(默認是
coordinates,可通過coordinatesKey指定) - 座標數據滿足 WKT 格式要求
我的發現:CSV 數據源和 JSON 數據源的格式要求類似,都支持 WKT 格式!
第五步:定義數據屬性
看到可以加載數據後,我想:能不能根據數據的不同屬性顯示不同的樣式?
文檔説可以用 defineAttribute 來定義數據屬性!
// 加載數據
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
// 定義顏色屬性
dataSource.defineAttribute('color', 'color');
// 定義大小屬性
dataSource.defineAttribute('size', 'size');
我的理解:defineAttribute 可以將數據中的字段映射到可視化屬性!
我的嘗試:
// 創建支持顏色和大小的點圖層
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),才能使用數據屬性!
使用回調函數定義屬性
文檔説可以用回調函數來動態計算屬性值:
// 使用回調函數定義顏色
dataSource.defineAttribute('color', properties => {
// 根據數據動態計算顏色
return properties.count > 100 ? 0xff0000 : 0x00ff00;
});
// 使用回調函數定義大小
dataSource.defineAttribute('size', properties => {
return properties.count * 2;
});
我的發現:回調函數可以靈活地根據數據計算屬性值!
第六步:動態修改數據
看到可以加載數據後,我想:能不能動態添加、刪除、修改數據?
文檔説數據源提供了 add、remove、setData 等方法來修改數據!
// 添加數據
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]);
我的發現:可以動態地添加、刪除、修改數據,非常靈活!
我的嘗試:
// 點擊地圖添加點
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 構造函數創建數據源!
// 創建數據源
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 可以表示不同類型的幾何圖形:
// 點數據
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 屬性來設置數據的投影信息!
// 創建使用投影座標的數據項
const item = new mapvthree.DataItem({
geometry: {
type: 'Point',
coordinates: [12960000, 4850000, 0], // 投影座標
},
}, {
crs: 'EPSG:3857', // 指定投影
});
我的理解:引擎會自動將數據從源投影轉換到目標投影!
我的發現:這樣就能處理不同座標系統的數據了!
第九步:完整示例
我想寫一個完整的示例,把學到的都用上:
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:屬性不生效
原因:沒有在可視化組件中開啓對應的屬性標誌。
解決:需要在組件中開啓對應的屬性標誌,如 vertexColors、vertexSizes。
坑 3:座標格式錯誤
原因:座標格式不符合要求,或者座標字段名不對。
解決:
- 確保座標格式正確(WKT 格式或數組格式)
- 使用
coordinatesKey指定座標字段名
坑 4:JSON/CSV 數據解析失敗
原因:座標數據不是 WKT 格式,且沒有自定義解析函數。
解決:使用 parseCoordinates 自定義解析函數。
坑 5:數據更新不生效
原因:使用了錯誤的方法更新數據。
解決:
- 更新整個數據源:使用
setData - 添加/刪除數據:使用
add/remove - 修改屬性:使用
setAttributeValues - 修改座標:使用
setCoordinates
我的學習總結
經過這一天的學習,我掌握了:
- 數據源的作用:存儲帶座標信息的數據,與可視化組件配合使用
- DataItem:數據的最小單元,可以表示點、線、面等幾何圖形
- GeoJSON 數據源:最常用的數據格式,支持
fromURL和fromGeoJSON - JSON 數據源:支持 WKT 格式座標,可以自定義解析函數
- CSV 數據源:支持 WKT 格式座標,格式要求與 JSON 類似
- 定義屬性:通過
defineAttribute將數據字段映射到可視化屬性 - 動態修改:通過
add、remove、setData等方法動態修改數據 - 數據投影:通過
crs屬性設置數據投影,引擎自動轉換
我的感受:數據源系統真的很強大!雖然功能很多,但是用起來其實不難。關鍵是要理解數據源和可視化組件的關係,然後根據數據格式選擇合適的加載方式!
下一步計劃:
- 學習更多數據源的配置選項
- 嘗試處理複雜的數據格式
- 做一個完整的數據可視化項目
學習筆記就到這裏啦!作為一個初學者,我覺得數據源系統雖然功能很多,但是用起來其實不難。關鍵是要理解數據源和可視化組件的關係,然後根據數據格式選擇合適的加載方式!希望我的筆記能幫到其他初學者!大家一起加油!