博客 / 詳情

返回

第一次接觸 JSAPIThree(百度地圖 JSAPI Three)學習筆記

作為一個前端小白,今天要開始學習百度地圖的 JSAPI Three(也叫 mapvthree)了!聽説這是一個超強的 3D 地圖渲染引擎,可以做出很酷炫的三維地圖效果。想想就激動!讓我記錄下學習的過程吧!🚀

第一天:聽説 JSAPIThree

今天在項目裏看到了一個新需求,要用 3D 地圖展示數據。我一開始還以為是普通的百度地圖 API,結果同事説要用 JSAPIThree,這是百度地圖的 3D 渲染引擎。

我的第一反應:3D 地圖?聽起來好高級!但是會不會很難啊?😅

查了一下資料才知道:

  • JSAPIThree = 百度地圖 JSAPI Three
  • 也叫 mapvthree(這是 npm 包名)
  • 基於 Three.js 開發
  • 可以做二三維一體化的地圖渲染

我的理解:簡單説就是百度地圖的 3D 版本,可以做出那種很酷炫的三維地圖效果,就像遊戲裏的地圖一樣!

第二天:開始安裝

第一步:安裝依賴

按照文檔,第一步是安裝依賴。文檔説需要安裝兩個包:

  • @baidumap/mapv-three:這是 JSAPIThree 的核心包
  • three:這是 Three.js,底層渲染引擎
npm i -S @baidumap/mapv-three three

我的操作:打開終端,執行命令...等待中...

我的發現:安裝成功了!但是看到依賴列表裏有很多包,看來這個庫還挺大的。

注意:文檔説如果用 pnpm v7 以上版本,可能會有警告,需要執行 pnpm approve-builds。我用的是 npm,所以沒遇到這個問題。

第二步:配置靜態資源

安裝完依賴後,我以為就能直接用了,結果文檔説還要配置靜態資源!

我的困惑:什麼是靜態資源?為什麼要配置?

看了文檔才知道,mapvthree 在初始化時需要加載一些資源文件(比如着色器、紋理等)。如果不配置,運行時會報錯:

"Unable to determine base URL automatically, try defining a global variable called MAPV_BASE_URL."

我的理解:就是告訴引擎,資源文件在哪裏。

我用的是 Vite

文檔説如果用 Vite 或 Rollup,需要這樣配置:

// vite.config.js
import copy from 'rollup-plugin-copy';

const viteConfig = {
    plugins: [
        copy({
            targets: [
                {src: 'node_modules/@baidumap/mapv-three/dist/assets', dest: 'public/mapvthree'},
            ],
            verbose: true,
            hook: 'buildStart',
        }),
        // ...其他插件
    ]
};

我的操作

  1. 先安裝 rollup-plugin-copynpm i -D rollup-plugin-copy
  2. vite.config.js 裏添加配置
  3. 重啓開發服務器

我的感受:配置過程有點複雜,但是按照文檔一步步來,還是能搞定的!

在 HTML 裏聲明全局變量

配置完構建工具後,還要在 index.html 裏聲明全局變量:

<!-- index.html -->
<script>
    window.MAPV_BASE_URL = 'mapvthree/';
</script>

我的理解:這個變量告訴引擎,資源文件在 mapvthree/ 目錄下。

我的操作:在 index.html<head> 里加上這段代碼。

第三步:配置百度地圖 AK

文檔説 mapvthree 默認展示百度地圖矢量數據,需要配置百度地圖開發者密鑰(AK)。

我的疑問:什麼是 AK?為什麼要配置?

查了一下才知道,AK 是百度地圖開放平台的密鑰,用來驗證身份和限制訪問量。

我的操作步驟

  1. 訪問百度地圖開放平台
  2. 登錄百度賬號(沒有的話要註冊)
  3. 點擊"創建應用"
  4. 填寫應用名稱,選擇"瀏覽器端"
  5. 創建完成後,獲得一個 AK 密鑰

我的感受:註冊和創建應用的過程還挺順利的,就是要注意選擇"瀏覽器端",不然可能用不了。

在代碼裏配置 AK

拿到 AK 後,要在項目入口文件裏配置:

// 在項目入口文件中配置(比如 main.js)
import * as mapvthree from '@baidumap/mapv-three';

// 配置百度地圖 AK
mapvthree.BaiduMapConfig.ak = '您的AK密鑰';

我的操作:在 main.js 里加上這段代碼,把 '您的AK密鑰' 替換成我申請的 AK。

我的發現:這個配置只需要全局執行一次就行,不用每次都配置。

第三天:第一個 Hello World!

配置完成後,終於可以開始寫代碼了!我按照文檔寫了個最簡單的例子。

第一步:引入庫

文檔説可以一次性引入所有組件,也可以按需引入。我選擇一次性引入,簡單直接:

import * as mapvthree from '@baidumap/mapv-three';

我的想法:先全部引入,等熟悉了再考慮按需引入優化。

第二步:初始化引擎

文檔説通過 Engine 類可以初始化一個三維場景。最簡單的用法是:

const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {
    // 可選的配置項
});

我的理解:就像創建一個畫布,container 是容器元素,engine 是引擎實例。

我的第一個嘗試

import * as mapvthree from '@baidumap/mapv-three';

// 獲取容器元素
const container = document.getElementById('container');

// 創建引擎
const engine = new mapvthree.Engine(container);

我的發現:運行後,頁面上出現了一個 3D 地圖!雖然很簡單,但是能看到地圖了,好激動!🎉

我的觀察

  • 默認有百度矢量底圖
  • 默認有天空(看起來像真實的天空)
  • 可以鼠標拖動旋轉視角
  • 可以滾輪縮放

我的感受:太神奇了!就幾行代碼,就能看到一個 3D 地圖!

第三步:瞭解配置選項

看到效果後,我開始好奇:能不能自定義地圖的位置、視角?

文檔説可以在初始化時傳入配置:

const engine = new mapvthree.Engine(container, {
    map: {
        center: [116.414, 39.915],  // 中心點座標(經度,緯度)
        range: 500,                 // 縮放級別(米)
        heading: 225,                // 方位角(度)
        pitch: 70,                   // 俯仰角(度)
    },
});

我的嘗試

const engine = new mapvthree.Engine(container, {
    map: {
        center: [116.404, 39.915],  // 北京天安門
        range: 1000,                 // 1000 米高度
        heading: 0,                  // 正北方向
        pitch: 60,                   // 60 度俯視
    },
});

我的發現:地圖定位到了天安門,視角也變了!pitch 越大,俯視角度越大,看起來越像從高空往下看。

我的理解

  • center:地圖中心點的經緯度
  • range:相機距離地面的高度(米),值越小越近
  • heading:水平旋轉角度,0 是正北,90 是正東
  • pitch:垂直俯仰角,0 是水平,90 是垂直向下

第四步:添加可視化組件

看到地圖後,我想:能不能在地圖上添加一些點?

文檔説可以用 SimplePoint 來展示點數據。但是需要先準備數據源。

我的第一次嘗試

// 創建數據源
const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            properties: {},
            geometry: {
                type: 'Point',
                coordinates: [116.414, 39.915],  // 一個點的座標
            },
        },
    ],
});

// 創建點圖層
const point = engine.add(new mapvthree.SimplePoint({
    size: 10,  // 點的大小
}));

// 關聯數據源
point.dataSource = dataSource;

我的發現:地圖上出現了一個紅色的點!雖然很小,但是能看到!

我的感受:成功添加了點!雖然代碼有點長,但是邏輯很清晰:

  1. 準備數據(GeoJSON 格式)
  2. 創建圖層
  3. 關聯數據

我的改進:我想添加多個點,試試:

const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            properties: {},
            geometry: {
                type: 'Point',
                coordinates: [116.404, 39.915],
            },
        },
        {
            type: 'Feature',
            properties: {},
            geometry: {
                type: 'Point',
                coordinates: [116.414, 39.925],
            },
        },
    ],
});

const point = engine.add(new mapvthree.SimplePoint({
    size: 20,  // 調大一點,看得清楚
}));
point.dataSource = dataSource;

我的發現:地圖上出現了兩個點!太棒了!

第五步:添加三維模型

看到點數據後,我想:能不能添加 3D 模型?比如建築物?

文檔説可以用 SimpleModel 來加載 3D 模型:

const model = engine.add(new mapvthree.SimpleModel({
    name: 'model',
    point: [116.414, 39.915],  // 模型的位置
    url: 'assets/models/building/5_tiyuzhongxin.glb',  // 模型文件路徑
}));

我的嘗試:我找了個 GLB 格式的模型文件,按照文檔寫代碼:

const model = engine.add(new mapvthree.SimpleModel({
    name: 'myBuilding',
    point: [116.404, 39.915],  // 天安門附近
    url: 'assets/models/building/5_tiyuzhongxin.glb',
}));

我的發現:地圖上出現了一個 3D 建築模型!可以旋轉視角看,太酷了!

我的感受:3D 模型在地圖上看起來特別真實,就像真的建築物一樣!

我的疑問:模型文件格式有什麼要求?

查了文檔才知道,支持常見的 3D 模型格式:

  • GLTF/GLB(推薦)
  • OBJ
  • FBX

我的理解:GLB 是 GLTF 的二進制版本,文件更小,加載更快,所以推薦用 GLB。

第六步:添加交互事件

看到模型後,我想:能不能點擊交互?

文檔説可以添加事件監聽:

point.addEventListener('click', (e) => {
    console.log('點擊了!', e);
});

我的嘗試

point.addEventListener('click', (e) => {
    console.log('點擊了點的數據:', e);
    alert('你點擊了一個點!');
});

我的發現:點擊點的時候,控制枱輸出了事件信息,還彈出了提示框!

我的感受:交互功能也很簡單,就是標準的 addEventListener

我的改進:我想在點擊時顯示更多信息:

point.addEventListener('click', (e) => {
    const coordinates = e.feature.geometry.coordinates;
    console.log('點擊的座標:', coordinates);
    alert(`經度:${coordinates[0]}\n緯度:${coordinates[1]}`);
});

我的發現:可以獲取點擊的座標信息!這樣就能做更多交互了!

第四天:深入瞭解引擎

發現引擎的屬性

看了文檔才知道,engine 對象有很多屬性:

  • engine.map:地圖相關操作(視野控制、座標轉換等)
  • engine.rendering:渲染相關配置(動畫循環、特效等)
  • engine.widgets:UI 控件(指南針、比例尺等)
  • engine.selection:模型選擇控制器
  • engine.clock:時鐘管理(控制時間,影響天空、光照等)
  • engine.camera:相機對象(Three.js 的相機)
  • engine.renderer:渲染器對象(Three.js 的渲染器)
  • engine.scene:場景對象(Three.js 的場景)

我的理解engine 就像一個總控制器,管理着地圖的各個方面。

嘗試視野操作

文檔説可以通過 engine.map 控制視野:

const center = [116.404, 39.915];
engine.map.lookAt(center, {
    heading: 0,
    pitch: 60,
    range: 2000,
});

我的嘗試

// 創建一個按鈕,點擊後飛到天安門
document.getElementById('flyToBtn').addEventListener('click', () => {
    engine.map.lookAt([116.404, 39.915], {
        heading: 0,
        pitch: 60,
        range: 1000,
    });
});

我的發現:點擊按鈕後,地圖會平滑地移動到天安門!就像動畫一樣!

我的感受:這個功能太實用了!可以做場景切換、視角動畫等效果!

嘗試渲染配置

文檔説可以通過 engine.rendering 配置渲染:

// 開啓循環渲染(用於動畫)
engine.rendering.enableAnimationLoop = true;

// 設置幀率
engine.rendering.animationLoopFrameTime = 16;  // 約 60 FPS

我的嘗試

// 開啓循環渲染
engine.rendering.enableAnimationLoop = true;

我的發現:開啓後,如果有動畫效果(比如飛線、粒子等),會持續播放!

我的理解:默認情況下,引擎只在需要時渲染(比如拖動地圖時)。開啓循環渲染後,每幀都會渲染,適合有動畫的場景。

嘗試添加和移除物體

文檔説可以用 engine.add 添加物體,用 engine.remove 移除物體:

// 添加物體
const point = engine.add(new mapvthree.SimplePoint());
const mesh = engine.add(new THREE.Mesh());

// 移除物體
engine.remove(point);
engine.remove(mesh);

我的嘗試

// 創建一個點
const point = engine.add(new mapvthree.SimplePoint({
    size: 20,
}));
point.dataSource = dataSource;

// 5 秒後移除
setTimeout(() => {
    engine.remove(point);
    console.log('點已移除');
}, 5000);

我的發現:5 秒後,點從地圖上消失了!

我的感受:添加和移除都很簡單,這樣就能動態控制地圖上的元素了!

第五天:完整示例

經過幾天的學習,我想寫一個完整的示例,把學到的都用上:

import * as mapvthree from '@baidumap/mapv-three';
import * as THREE from 'three';

// 獲取容器
const container = document.getElementById('container');

// 創建引擎
const engine = new mapvthree.Engine(container, {
    map: {
        center: [116.404, 39.915],  // 天安門
        range: 1000,
        heading: 0,
        pitch: 60,
    },
    rendering: {
        enableAnimationLoop: true,  // 開啓循環渲染
    },
});

// 創建數據源(兩個點)
const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            properties: { name: '點1' },
            geometry: {
                type: 'Point',
                coordinates: [116.404, 39.915],
            },
        },
        {
            type: 'Feature',
            properties: { name: '點2' },
            geometry: {
                type: 'Point',
                coordinates: [116.414, 39.925],
            },
        },
    ],
});

// 創建點圖層
const point = engine.add(new mapvthree.SimplePoint({
    size: 30,
}));
point.dataSource = dataSource;

// 添加點擊事件
point.addEventListener('click', (e) => {
    const name = e.feature.properties.name;
    const coords = e.feature.geometry.coordinates;
    alert(`${name}\n經度:${coords[0]}\n緯度:${coords[1]}`);
});

// 添加 3D 模型
const model = engine.add(new mapvthree.SimpleModel({
    name: 'building',
    point: [116.404, 39.915],
    url: 'assets/models/building/5_tiyuzhongxin.glb',
}));

我的感受:寫一個完整的示例,把學到的都用上,感覺很有成就感!

我的發現

  • 地圖可以正常顯示
  • 點數據可以正常顯示
  • 點擊事件可以正常觸發
  • 3D 模型可以正常加載

雖然代碼還很簡單,但是已經能做出一個基本的 3D 地圖應用了!

我的學習總結

經過這幾天的學習,我掌握了:

  1. 安裝和配置

    • 安裝依賴包
    • 配置靜態資源
    • 配置百度地圖 AK
  2. 基礎使用

    • 初始化引擎
    • 配置地圖參數
    • 添加可視化組件
    • 添加 3D 模型
    • 添加交互事件
  3. 引擎屬性

    • engine.map:地圖控制
    • engine.rendering:渲染配置
    • engine.add / engine.remove:添加/移除物體

我的感受

  • JSAPIThree 功能很強大,但是上手不難
  • 文檔很詳細,按照文檔一步步來就能學會
  • 代碼結構清晰,API 設計合理
  • 能做出來的效果很酷炫!

我的下一步計劃

  1. 學習更多可視化組件(線、面、熱力圖等)
  2. 學習數據源的使用(CSV、JSON 等)
  3. 學習特效和動畫
  4. 做一個完整的項目

我的建議

  • 初學者可以先從最簡單的例子開始
  • 多動手實踐,看文檔不如寫代碼
  • 遇到問題先查文檔,再查社區
  • 不要怕出錯,多試幾次就會了

學習筆記就到這裏啦!作為一個初學者,我覺得 JSAPIThree 雖然功能強大,但是學習曲線並不陡峭。只要按照文檔一步步來,多動手實踐,很快就能做出酷炫的 3D 地圖效果!大家一起加油!💪
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.