看過的知識不等于學會。唯有用心總結、系統記錄,并通過溫故知新反復實踐,才能真正掌握一二
作為一名摸爬滾打三年的前端開發,開源社區給了我飯碗,我也將所學的知識體系回饋給大家,助你少走彎路!
OpenLayers、Leaflet 快速入門 ,每周保持更新 2 個案例
Cesium 快速入門,每周保持更新 4 個案例
OpenLayers 快速入門(一)Map對象
OpenLayers 快速入門(二)Layer 對象
OpenLayers 快速入門(三)Source 對象補充
OpenLayers 快速入門(四)View 對象
OpenLayers 快速入門(五)Controls 對象
OpenLayers 快速入門(六)Interaction 對象
OpenLayers 快速入門(七)矢量數據
OpenLayers 快速入門(八)事件系統
OpenLayers 快速入門(九)Extent 介紹
OpenLayers 快速入門(十)常用 API 補充
View 對象:地圖視圖控制中心
View 是 OpenLayers 中控制地圖顯示狀態的核心組件,負責管理地圖的中心點、縮放級別、旋轉角度和坐標系等關鍵參數。
核心屬性
屬性名 | 類型 | 默認值 | 描述 |
---|---|---|---|
center | Array | [0, 0] | 地圖中心坐標(地圖投影坐標系) |
constrainRotation | boolean | true | 是否約束旋轉角度為 0、90、180、270 度(默認為 false) |
zoom | number | undefined | 僅在 resolution 未定義時使用。用于計算視圖初始分辨率的縮放級別 |
projection | string | ‘EPSG:3857’ | 地圖坐標系(如’EPSG:4326’) |
minZoom | number | 0 | 最小縮放級別 |
maxZoom | number | 28 | 最大縮放級別 |
resolution | number | undefined | 分辨率(替代 zoom 使用) |
resolutions | Array | undefined | 分辨率數組(用于自定義縮放級別) |
rotation | number | 0 | 旋轉角度(弧度) |
extent | Array | undefined | 地圖視圖的邊界限制([minx, miny, maxx, maxy]) |
constrainOnlyCenter | boolean | false | 是否僅限制中心點在 extent 內(默認為限制整個視圖) |
constrainResolution | boolean | false | 是否將縮放操作約束為固定分辨率(整數級別) |
smoothExtentConstraint | boolean | true | 是否平滑過渡到約束范圍 |
enableRotation | boolean | true | 是否允許旋轉 |
maxResolution | number | undefined | 最大分辨率 |
minResolution | number | undefined | 最小分辨率 |
zoomFactor | number | 2 | 縮放因子(每次縮放的比例) |
multiWorld | boolean | false | 是否允許地圖在世界范圍外平移(WGS84 投影下通常設為 true) |
// 中國區域推薦配置
const view = new View({projection: "EPSG:4326", // 使用經緯度坐標center: [116.4, 39.9], // 北京市中心zoom: 10,minZoom: 3, // 限制最小縮放maxZoom: 18, // 限制最大縮放constrainResolution: true, // 整數縮放級別multiWorld: true, // 允許超出經度-180~180范圍
});
projection
- 定義地圖坐標系,
EPSG:3857
為 Web 墨卡托投影(默認),EPSG:4326
為 WGS84 經緯度坐標系(常用)。 - 所有圖層必須使用相同投影
new View({projection: "EPSG:4326", // 使用經緯度坐標系
});
- 經緯度 -> 墨卡托投影坐標
import { fromLonLat } from "ol/proj";new View({center: fromLonLat([116.4, 39.9]), // 將經緯度轉換為EPSG:3857坐標
});
- 墨卡托投影坐標 -> 經緯度
import { toLonLat } from "ol/proj";
const lonLat = toLonLat([1296000, 4820000]); // 將墨卡托投影坐標轉換為經緯度
console.log(lonLat); // 輸出經緯度坐標[11.642166082188997, 39.68311704790915]
transform
將坐標從源投影轉換到目標投影。這會返回一個新的坐標(并且不會修改原始坐標)
import { transform } from "ol/proj";// 經緯度坐標轉換為墨卡托投影坐標
var mercator = transform([116.4074, 39.9042], "EPSG:4326", "EPSG:3857");
console.log(mercator); // 輸出:[12958412.492568914, 4852030.634814578]// 墨卡托投影坐標轉換為經緯度坐標
var lonlat = transform([12958412.492568914, 4852030.634814578],"EPSG:3857","EPSG:4326"
);
console.log(lonlat); // 輸出:[116.4074, 39.9042]
center
設置地圖中心點坐標,一般使用經緯度坐標
new View({center: [116.4074, 39.9042], // 北京市中心坐標projection: "EPSG:4326", // 使用經緯度坐標系
});
zoom
設置地圖縮放級別,如果設置了 resolution,則 zoom 會被忽略
new View({zoom: 10.5, // 設置縮放級別,可以為小數
});
minZoom & maxZoom
限制縮放級別范圍,只影響用戶交互和 API 縮放,不影響直接設置 resolution
new View({minZoom: 3,maxZoom: 18,zoom: 10,
});
rotation
視圖的初始旋轉角度,以弧度表示(正旋轉為順時針方向,0 表示北方)
new View({rotation: Math.PI / 4, // 旋轉45度
});
extent
設置地圖邊界,此范圍之外的內容無法在地圖上顯示,值為[minx, miny, maxx, maxy]
// 限制視圖在北京市范圍內
new View({extent: [115.4, 39.4, 117.5, 41.0],
});
resolution
直接設置分辨率,一般直接設置zoom
即可,除非需要精確控制顯示比例時使用
// 在EPSG:3857中,zoom0的分辨率約為156543.03392804097
new View({resolution: 78271.51696402048, // 相當于zoom1
});
核心方法
方法名 | 描述 |
---|---|
getCenter() | 獲取當前視圖中心坐標 |
setCenter(center) | 設置視圖中心 |
getZoom() | 獲取當前縮放級別(整數或小數) |
setZoom(zoom) | 設置縮放級別(立即生效) |
getRotation() | 獲取當前旋轉角度(弧度) |
setRotation(rotation) | 設置旋轉角度(弧度) |
getProjection() | 獲取當前投影對象 |
getResolution() | 獲取當前分辨率 |
setResolution(resolution) | 設置分辨率(立即生效) |
getResolutions() | 獲取分辨率數組(如果設置) |
getMinZoom() | 獲取最小縮放級別 |
setMinZoom(zoom) | 設置最小縮放級別 |
getMaxZoom() | 獲取最大縮放級別 |
setMaxZoom(zoom) | 設置最大縮放級別 |
getMinResolution() | 獲取最小分辨率 |
getMaxResolution() | 獲取最大分辨率 |
animate(animation) | 執行動畫效果(移動、縮放、旋轉等) |
cancelAnimations() | 取消任何正在進行的動畫 |
fit(geometry, options) | 調整視圖以適配指定幾何體或范圍 |
calculateExtent(size) | 計算當前視圖的范圍(需傳入地圖容器尺寸[width, height]) |
視圖控制方法
// 獲取當前視圖狀態
const center = view.getCenter();
const zoom = view.getZoom();
const rotation = view.getRotation();// 設置視圖狀態(立即生效)
view.setCenter([13500000, 4500000]);
view.setZoom(8);
view.setRotation(Math.PI / 6);
animate() - 動畫效果
執行平滑的視圖過渡,單個動畫配置對象或數組
動畫配置屬性
屬性名 | 類型 | 描述 |
---|---|---|
center | Array | 目標中心 |
zoom | number | 目標縮放 |
resolution | number | 目標分辨率 |
rotation | number | 目標旋轉 |
duration | number | 動畫時長(毫秒) |
easing | function | 緩動函數 參考 常用 api |
// 平滑移動到新位置
view.animate({center: [116.4, 39.9],zoom: 14,duration: 2000,easing: ol.easing.easeIn,
});// 鏈式動畫:先縮放后移動
view.animate([{ zoom: 10, duration: 1500 },{ center: [121.4, 31.2], duration: 1000 },
]);
fit() - 適配顯示
fit(geometryOrExtent, options)
自動調整視圖以完整顯示指定區域
-
geometryOrExtent
:適配視圖的幾何形狀或范圍 -
options
:適配選項對象,包含以下屬性:
選項名 | 類型 | 默認值 | 描述 |
---|---|---|---|
size | Array | 地圖容器尺寸 | 用于計算適配的容器尺寸([width, height]) |
padding | Array | [0,0,0,0] | 內邊距([top, right, bottom, left]) |
minResolution | number | 0 | 適配的最小分辨率 |
maxZoom | number | undefined | 適配的最大縮放級別 |
duration | number | undefined | 動畫時長(毫秒) |
easing | function | undefined | 緩動函數 |
callback | function | undefined | 動畫完成后的回調函數 |
<template><div ref="mapContainer" id="map"></div><div style="position: absolute; top: 10px; left: 100px; z-index: 1000"><button @click="goto">定位到polygon區域</button></div>
</template><script setup>
import { ref, onMounted } from "vue";
import Map from "ol/Map.js";
import XYZ from "ol/source/XYZ.js";
import TileLayer from "ol/layer/Tile.js";
import View from "ol/View.js";
import "ol/ol.css";
import Polygon from "ol/geom/Polygon.js";
import Style from "ol/style/Style";
import Fill from "ol/style/Fill";
import Stroke from "ol/style/Stroke";
import Vector from "ol/source/Vector.js";
import VectorLayer from "ol/layer/Vector.js";
import Feature from "ol/Feature.js";const mapContainer = ref(null);
let map = null;
let view = null;
let polygon = null;
onMounted(() => {initMap();
});
const initMap = () => {view = new View({center: [116.4, 39.9], // 北京市中心經緯度zoom: 10.5,projection: "EPSG:4326", // 默認使用球面墨卡托投影(EPSG:3857),需要設置為WGS 84(EPSG:4326)經緯度// extent: [115.4, 39.4, 117.5, 41.0],});map = new Map({target: mapContainer.value,layers: [new TileLayer({// 設置高德地圖為數據源底圖source: new XYZ({// 矢量圖(含路網、含注記)url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7 ",}),}),],view,});polygon = new Polygon([[[117.4, 39.9],[117.5, 39.9],[117.5, 40.0],[117.4, 40.0],[117.4, 39.9],],]);// 將polygon渲染到地圖上,設置顏色為紅色const feature = new Feature({geometry: polygon,});const source = new Vector({features: [feature],});const layer = new VectorLayer({source,style: new Style({fill: new Fill({color: "rgba(255, 0, 0, 0.5)", // 半透明紅色填充}),stroke: new Stroke({color: "red", // 紅色邊框width: 2,}),}),});map.addLayer(layer);
};
const goto = () => {// 定位到polygon區域view.fit(polygon, {padding: [50, 50, 50, 50], // 四周留白duration: 3000,maxZoom: 15,});
};
</script>
<style scoped>
#map {position: absolute;top: 0;bottom: 0;width: 100%;
}
</style>
效果視頻
calculateExtent()
通過傳入地圖容器的尺寸,計算當前視圖的范圍。返回值為 [minX, minY, maxX, maxY]
。
// 計算當前視圖范圍
const mapSize = map.getSize();
const currentExtent = view.calculateExtent(mapSize);
console.log(currentExtent); // 輸出范圍 [minX, minY, maxX, maxY]