博客 / 詳情

返回

JSAPIThree 數據源系統學習筆記:讓數據在地圖上可視化

作為一個剛開始學習 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 數據源需要滿足特定格式:

  1. 有座標字段(默認是 coordinates,可通過 coordinatesKey 指定)
  2. 座標數據滿足 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 數據源也需要滿足特定格式:

  1. 有座標列(默認是 coordinates,可通過 coordinatesKey 指定)
  2. 座標數據滿足 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;
});

我的發現:回調函數可以靈活地根據數據計算屬性值!

第六步:動態修改數據

看到可以加載數據後,我想:能不能動態添加、刪除、修改數據?

文檔説數據源提供了 addremovesetData 等方法來修改數據!

// 添加數據
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:屬性不生效

原因:沒有在可視化組件中開啓對應的屬性標誌。

解決:需要在組件中開啓對應的屬性標誌,如 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. 做一個完整的數據可視化項目

學習筆記就到這裏啦!作為一個初學者,我覺得數據源系統雖然功能很多,但是用起來其實不難。關鍵是要理解數據源和可視化組件的關係,然後根據數據格式選擇合適的加載方式!希望我的筆記能幫到其他初學者!大家一起加油!

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.