作為一個剛開始學習 mapvthree 的小白,今天要學習地圖視野控制了!聽説這個模塊可以控制地圖的視角、縮放、旋轉等,還能轉換座標!想想就激動!
第一次聽説地圖視野控制
今天在文檔裏看到了 engine.map 這個詞,一開始我還以為是地圖本身,結果查了一下才知道,原來這是用來控制地圖視野的模塊!
文檔説地圖視野控制可以:
- 控制地圖的中心點位置
- 控制地圖的縮放級別
- 控制地圖的旋轉角度
- 控制地圖的俯仰角
- 轉換座標系統
- 切換視野動畫
我的理解:簡單説就是控制"怎麼看地圖",比如看哪裏、看多遠、從什麼角度看!就像控制相機一樣!
第一步:發現引擎的地圖屬性
作為一個初學者,我習慣先看看引擎有哪些屬性。文檔説 engine.map 就是地圖管理器!
我的發現:原來引擎創建後,就自動有了一個地圖管理器對象!不需要手動創建,直接用就行!
import * as mapvthree from '@baidumap/mapv-three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container);
// 地圖管理器已經自動創建了!
console.log(engine.map); // 可以訪問地圖管理器
我的理解:engine.map 就是地圖視野控制的入口,所有視野相關的操作都通過它來完成。
第二步:設置地圖中心點
文檔説可以通過 engine.map.setCenter() 來設置地圖的中心點。我試了試:
// 設置中心點為北京天安門
engine.map.setCenter([116.404, 39.915]);
我的發現:設置中心點後,地圖會立即移動到指定位置!
我的嘗試:我寫了個簡單的測試:
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: 1000,
pitch: 60,
},
});
// 切換到上海
engine.map.setCenter([121.473, 31.230]);
我的觀察:地圖從北京跳到了上海!雖然有點突然,但是位置確實變了!
我的理解:setCenter() 接受一個經緯度數組 [經度, 緯度],地圖會立即移動到該位置。
第三步:獲取當前中心點
看到可以設置中心點後,我開始好奇:能不能獲取當前的中心點?
文檔説可以用 engine.map.getCenter() 來獲取!
// 獲取當前中心點
const center = engine.map.getCenter();
console.log(center); // [116.404, 39.915]
我的發現:可以獲取當前的經緯度座標!
我的想法:如果做位置記錄功能,可以用這個方法來保存當前位置!
第四步:控制地圖縮放
看到中心點控制後,我想:能不能控制地圖的縮放?
文檔説可以通過 engine.map.setRange() 來控制視野距離地面的距離!
// 設置視野距離為 1000 米(比較近)
engine.map.setRange(1000);
// 設置視野距離為 10000 米(比較遠)
engine.map.setRange(10000);
我的理解:range 是相機距離地面的高度(米),值越小越近,值越大越遠。
我的嘗試:
// 拉近視野(1000 米)
engine.map.setRange(1000);
// 拉遠視野(10000 米)
engine.map.setRange(10000);
我的發現:
range = 1000:視野很近,能看到細節range = 10000:視野很遠,能看到更大的範圍
我的想法:如果做縮放功能,可以用這個方法來控制視野距離!
使用 setZoom 控制縮放
文檔還説可以用 setZoom() 來控制縮放級別!
// 設置縮放級別
engine.map.setZoom(14);
我的理解:zoom 是縮放級別,數字越大越近,數字越小越遠。
我的嘗試:
// 放大(級別 18)
engine.map.setZoom(18);
// 縮小(級別 10)
engine.map.setZoom(10);
我的發現:setZoom() 和 setRange() 都能控制縮放,但是 setZoom() 更直觀!
我的想法:如果做縮放按鈕,可以用 zoomIn() 和 zoomOut() 方法!
// 放大
engine.map.zoomIn();
// 縮小
engine.map.zoomOut();
我的發現:這兩個方法更方便,不需要知道具體的縮放級別!
第五步:控制地圖旋轉
看到縮放控制後,我想:能不能控制地圖的旋轉?
文檔説可以通過 engine.map.setHeading() 來設置旋轉角度!
// 設置旋轉角度(0 度是正北)
engine.map.setHeading(0);
// 設置旋轉角度(90 度是正東)
engine.map.setHeading(90);
我的理解:heading 是旋轉角度,以正北為 0 度,逆時針方向遞增。
我的嘗試:
// 正北方向
engine.map.setHeading(0);
// 正東方向
engine.map.setHeading(90);
// 正南方向
engine.map.setHeading(180);
// 正西方向
engine.map.setHeading(270);
我的發現:地圖會旋轉到指定方向!
我的想法:如果做指南針功能,可以用這個方法來控制方向!
獲取當前旋轉角度
文檔説可以用 getHeading() 來獲取當前的旋轉角度!
// 獲取當前旋轉角度
const heading = engine.map.getHeading();
console.log(heading); // 例如:45
我的發現:可以獲取當前的旋轉角度,這樣就能知道地圖朝向哪個方向了!
第六步:控制地圖俯仰角
看到旋轉控制後,我想:能不能控制地圖的俯仰角?
文檔説可以通過 engine.map.setPitch() 來設置俯仰角!
// 設置俯仰角(0 度是垂直向下看)
engine.map.setPitch(0);
// 設置俯仰角(90 度是水平看)
engine.map.setPitch(90);
我的理解:pitch 是俯仰角,0 度是垂直向下看,90 度是水平看。
我的嘗試:
// 垂直向下看(俯視)
engine.map.setPitch(0);
// 45 度俯視
engine.map.setPitch(45);
// 水平看(平視)
engine.map.setPitch(90);
我的發現:
pitch = 0:完全俯視,像從正上方看pitch = 45:斜向下看,能看到側面pitch = 90:水平看,像站在地面上看
我的想法:如果做視角切換功能,可以用這個方法來控制俯仰角!
獲取當前俯仰角
文檔説可以用 getPitch() 來獲取當前的俯仰角!
// 獲取當前俯仰角
const pitch = engine.map.getPitch();
console.log(pitch); // 例如:60
我的發現:可以獲取當前的俯仰角,這樣就能知道地圖的視角了!
第七步:使用 lookAt 設置視野
看到可以分別設置中心點、縮放、旋轉、俯仰角後,我想:能不能一次性設置所有參數?
文檔説可以用 engine.map.lookAt() 來一次性設置視野!
engine.map.lookAt(
[116.404, 39.915], // 中心點
{
heading: 0, // 旋轉角度
pitch: 60, // 俯仰角
range: 1000, // 視野距離
}
);
我的理解:lookAt() 可以一次性設置中心點、旋轉角度、俯仰角和視野距離,更方便!
我的嘗試:
// 飛到天安門,正北方向,60 度俯視,1000 米高度
engine.map.lookAt(
[116.404, 39.915],
{
heading: 0,
pitch: 60,
range: 1000,
}
);
我的發現:地圖會立即切換到指定視野,所有參數一次性設置!
我的想法:如果做場景切換功能,可以用這個方法來快速切換視野!
第八步:使用 flyTo 實現平滑過渡
看到 lookAt() 後,我想:能不能讓視野切換有動畫效果?
文檔説可以用 engine.map.flyTo() 來實現平滑的動畫過渡!
engine.map.flyTo(
[116.404, 39.915], // 目標位置
{
heading: 0,
pitch: 60,
range: 1000,
duration: 2000, // 動畫持續時間(毫秒)
}
);
我的理解:flyTo() 和 lookAt() 功能類似,但是 flyTo() 有平滑的動畫效果!
我的嘗試:
// 平滑飛到天安門
engine.map.flyTo(
[116.404, 39.915],
{
heading: 0,
pitch: 60,
range: 1000,
duration: 2000, // 2 秒動畫
}
);
我的發現:地圖會平滑地飛到目標位置,有動畫效果,看起來很舒服!
我的感受:flyTo() 比 lookAt() 更友好,用户體驗更好!
我的想法:如果做場景切換,應該用 flyTo() 而不是 lookAt()!
flyTo 的回調函數
文檔説 flyTo() 還支持回調函數!
engine.map.flyTo(
[116.404, 39.915],
{
duration: 2000,
complete: () => {
console.log('動畫完成!');
},
cancel: () => {
console.log('動畫取消!');
},
}
);
我的發現:可以在動畫完成或取消時執行回調函數,這樣就能做更多操作了!
我的想法:如果做場景切換,可以在動畫完成後加載數據或顯示信息!
第九步:座標轉換
看到視野控制後,我開始好奇:什麼是座標轉換?
文檔説可以通過 projectCoordinate() 和 unprojectCoordinate() 來轉換座標!
我的理解:地理座標(經緯度)和投影座標(米)之間可以互相轉換!
地理座標轉投影座標
import * as THREE from 'three';
// 地理座標(經緯度)
const geoCoord = new THREE.Vector3(116.404, 39.915, 0);
// 投影座標(米)
const projCoord = new THREE.Vector3();
engine.map.projectCoordinate(geoCoord, projCoord);
console.log(projCoord); // 投影座標
我的理解:projectCoordinate() 把地理座標轉換為投影座標。
我的發現:投影座標是三維座標(x, y, z),單位是米,可以用來放置 3D 物體!
投影座標轉地理座標
import * as THREE from 'three';
// 投影座標(米)
const projCoord = new THREE.Vector3(12960000, 4850000, 0);
// 地理座標(經緯度)
const geoCoord = new THREE.Vector3();
engine.map.unprojectCoordinate(projCoord, geoCoord);
console.log(geoCoord); // 地理座標
我的理解:unprojectCoordinate() 把投影座標轉換為地理座標。
我的發現:可以從投影座標轉換回經緯度,這樣就能知道 3D 物體對應的地理位置了!
數組座標轉換
文檔還説可以用 projectArrayCoordinate() 來轉換數組格式的座標!
// 地理座標數組
const geoArray = [116.404, 39.915];
// 投影座標數組
const projArray = engine.map.projectArrayCoordinate(geoArray, []);
console.log(projArray); // [x, y, z]
我的發現:數組格式更方便,不需要創建 Vector3 對象!
我的想法:如果做批量座標轉換,可以用數組格式!
第十步:瞭解投影方式
看到座標轉換後,我開始好奇:什麼是投影?
文檔説可以通過 engine.map.projection 來獲取投影方式!
我的理解:投影是把地球的球面座標轉換為平面座標的方法。
投影類型
文檔説支持三種投影方式:
- EPSG:4326:WGS84 座標系,經緯度形式
- EPSG:3857:Web 墨卡託投影,單位為米(默認)
- EPSG:4978:ECEF 座標系,單位為米(3D 地球)
我的嘗試:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:3857', // Web 墨卡託投影(默認)
center: [116.404, 39.915],
range: 1000,
},
});
我的發現:可以在初始化時設置投影方式!
我的理解:
EPSG:4326:適合顯示經緯度座標EPSG:3857:適合顯示平面地圖(默認)EPSG:4978:適合顯示 3D 地球
我的想法:如果做 3D 地球效果,應該用 EPSG:4978!
第十一步:設置視野範圍
看到座標轉換後,我想:能不能限制地圖的可拖動範圍?
文檔説可以用 engine.map.setBounds() 來設置視野範圍!
// 設置視野範圍(左下角和右上角座標)
engine.map.setBounds([
[116.0, 39.0], // 左下角
[117.0, 40.0], // 右上角
]);
我的理解:setBounds() 限制地圖只能在指定區域內拖動。
我的嘗試:
// 限制在北京範圍內
engine.map.setBounds([
[116.0, 39.5], // 左下角
[117.0, 40.5], // 右上角
]);
我的發現:設置後,地圖只能在指定區域內拖動,超出範圍會自動限制!
我的想法:如果做區域展示,可以用這個方法來限制視野範圍!
獲取當前視野範圍
文檔説可以用 getBounds() 來獲取當前的視野範圍!
// 獲取當前視野範圍
const bounds = engine.map.getBounds();
console.log(bounds); // Box3 對象
我的發現:可以獲取當前可視區域的邊界,這樣就能知道地圖顯示的範圍了!
第十二步:根據座標數組設置視野
看到視野範圍後,我想:能不能根據一組座標自動調整視野?
文檔説可以用 engine.map.setViewport() 來根據座標數組設置視野!
// 根據座標數組設置視野
engine.map.setViewport(
[
[116.404, 39.915],
[116.414, 39.925],
[116.424, 39.935],
],
{
range: 5000, // 視野距離
}
);
我的理解:setViewport() 會根據座標數組自動計算合適的視野,讓所有座標都在視野內。
我的嘗試:
// 顯示多個點的視野
const points = [
[116.404, 39.915], // 點 1
[116.414, 39.925], // 點 2
[116.424, 39.935], // 點 3
];
engine.map.setViewport(points, {
range: 5000,
});
我的發現:地圖會自動調整視野,讓所有點都在視野內!
我的想法:如果做數據展示,可以用這個方法來自動調整視野,顯示所有數據點!
第十三步:縮放到對象範圍
看到 setViewport() 後,我想:能不能縮放到某個 3D 對象的範圍?
文檔説可以用 engine.map.zoomTo() 來縮放到對象範圍!
import * as THREE from 'three';
// 創建一個 3D 對象
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
engine.add(mesh);
// 縮放到對象範圍
engine.map.zoomTo(mesh, {
range: 1000,
});
我的理解:zoomTo() 會自動調整視野,讓指定的 3D 對象在視野內。
我的發現:地圖會自動調整視野,讓對象在視野中心!
我的想法:如果做模型查看功能,可以用這個方法來自動調整視野!
第十四步:設置視野限制
看到視野控制後,我想:能不能限制視野的最大最小距離?
文檔説可以用 setMaxRange() 和 setMinRange() 來設置視野限制!
// 設置最大視野距離(不能拉得太遠)
engine.map.setMaxRange(100000);
// 設置最小視野距離(不能拉得太近)
engine.map.setMinRange(100);
我的理解:setMaxRange() 和 setMinRange() 限制視野的距離範圍。
我的嘗試:
// 限制視野在 100 米到 10000 米之間
engine.map.setMinRange(100);
engine.map.setMaxRange(10000);
我的發現:設置後,用户無法將視野拉得太近或太遠,會被限制在指定範圍內!
我的想法:如果做特定場景,可以用這個方法來限制視野範圍!
第十五步:獲取相機位置
看到視野控制後,我想:能不能獲取當前相機的位置?
文檔説可以用 engine.map.getCameraLocation() 來獲取相機位置!
import * as THREE from 'three';
// 獲取相機位置
const cameraPos = new THREE.Object3D();
const location = engine.map.getCameraLocation(cameraPos);
console.log(location); // 相機位置的經緯度和高度
我的發現:可以獲取當前相機的經緯度座標和高度!
我的想法:如果做相機位置記錄,可以用這個方法來保存相機位置!
第十六步:做一個完整的示例
我想寫一個完整的示例,把學到的都用上:
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: 1000,
pitch: 60,
heading: 0,
},
});
// 創建按鈕控制視野
document.getElementById('flyToBtn').addEventListener('click', () => {
// 平滑飛到天安門
engine.map.flyTo(
[116.404, 39.915],
{
heading: 0,
pitch: 60,
range: 1000,
duration: 2000,
complete: () => {
console.log('到達天安門!');
},
}
);
});
document.getElementById('lookAtBtn').addEventListener('click', () => {
// 立即切換到上海
engine.map.lookAt(
[121.473, 31.230],
{
heading: 0,
pitch: 60,
range: 2000,
}
);
});
document.getElementById('zoomInBtn').addEventListener('click', () => {
// 放大
engine.map.zoomIn();
});
document.getElementById('zoomOutBtn').addEventListener('click', () => {
// 縮小
engine.map.zoomOut();
});
// 獲取當前視野信息
const center = engine.map.getCenter();
const range = engine.map.getRange();
const heading = engine.map.getHeading();
const pitch = engine.map.getPitch();
console.log('中心點:', center);
console.log('視野距離:', range);
console.log('旋轉角度:', heading);
console.log('俯仰角:', pitch);
我的感受:寫一個完整的示例,把學到的都用上,感覺很有成就感!
我的發現:
- 可以控制地圖視野
- 可以實現平滑動畫
- 可以獲取視野信息
- 可以轉換座標
雖然代碼還很簡單,但是已經能做出一個基本的地圖視野控制系統了!
第十七步:踩過的坑
作為一個初學者,我踩了不少坑,記錄下來避免再犯:
坑 1:座標格式寫錯了
原因:經緯度順序寫反了,或者格式不對。
解決:座標格式是 [經度, 緯度],經度在前,緯度在後。
坑 2:flyTo 和 lookAt 的區別不清楚
原因:不知道什麼時候用 flyTo,什麼時候用 lookAt。
解決:
lookAt:立即切換視野,沒有動畫flyTo:平滑切換視野,有動畫效果
坑 3:range 和 zoom 的區別不清楚
原因:不知道 range 和 zoom 的區別。
解決:
range:視野距離地面的高度(米),值越小越近zoom:縮放級別,數字越大越近
坑 4:投影方式設置不對
原因:投影方式設置錯誤,導致座標轉換失敗。
解決:根據需求選擇合適的投影方式,默認是 EPSG:3857。
坑 5:座標轉換時沒有創建輸出對象
原因:座標轉換時沒有創建輸出對象。
解決:座標轉換需要提供輸出對象,比如 new THREE.Vector3()。
我的學習總結
經過這一天的學習,我掌握了:
- 地圖視野控制的作用:控制地圖的視角、縮放、旋轉等
- 如何設置中心點:通過
setCenter()設置 - 如何控制縮放:通過
setRange()或setZoom()控制 - 如何控制旋轉:通過
setHeading()設置旋轉角度 - 如何控制俯仰角:通過
setPitch()設置俯仰角 - 如何切換視野:通過
lookAt()或flyTo()切換 - 如何轉換座標:通過
projectCoordinate()和unprojectCoordinate()轉換 - 如何設置視野範圍:通過
setBounds()限制視野範圍 - 如何自動調整視野:通過
setViewport()根據座標數組自動調整
我的感受:地圖視野控制真的很強大!雖然功能很多,但是用起來其實不難。關鍵是要理解每個方法的作用,然後根據需求選擇合適的方法!
下一步計劃:
- 學習更多高級的視野控制功能
- 嘗試創建複雜的視野切換動畫
- 做一個完整的地圖導航項目
學習筆記就到這裏啦!作為一個初學者,我覺得地圖視野控制雖然功能很多,但是用起來其實不難。關鍵是要理解每個方法的作用,然後根據需求選擇合適的方法!希望我的筆記能幫到其他初學者!大家一起加油!