Skip to content

OpenLayers 用于在网页上显示地图

1.介绍

OpenLayers 是一个开源的 JavaScript 库,用于在网页上显示地图。它支持多种地图源,包括 OSM、Bing、MapQuest 等。

学习网站

官网:https://openlayers.org/

2.基础使用

2.1.安装

npm install ol

2.2.基础使用

vue
<template>
  <div id="openLayers-container"></div>
</template>

<script setup>
import { onMounted } from 'vue';

import 'ol/ol.css';
import { Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';

onMounted(() => {
  const map = new Map({
    target: 'openLayers-container', // 地图容器的ID
    layers: [
      new TileLayer({
        source: new OSM(), // 使用OpenStreetMap作为底图
      }),
    ],
    view: new View({
      center: [0, 0], // 地图中心坐标
      zoom: 2, // 初始缩放级别
    }),
  });
});
</script>

<style scoped>
#openLayers-container {
  width: 100%;
  height: 500px;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

3.地图、图层、要素

3.1.地图(Map)

  • 地图是 OpenLayers 的核心对象,用于管理图层、视图和用户交互。
  • 一个地图可以包含多个图层,并控制它们的显示和交互。

3.2.图层(Layer)

  • 图层是地图的组成部分,用于显示地理数据。
  • 常见的图层类型包括:
    • TileLayer:用于显示瓦片地图(如 OpenStreetMap)。
    • VectorLayer:用于显示矢量数据(如点、线、面等要素)。

3.3.要素(Feature)

  • 要素是地理空间数据的基本单位,可以是点、线、面等几何对象。
  • 要素可以附加属性数据,并显示在矢量图层上
vue
<template>
  <div id="openLayers-container1"></div>
</template>

<script setup>
import { onMounted } from 'vue';


import 'ol/ol.css'; // 引入 OpenLayers 的样式
import { Map, View } from 'ol'; // 引入 Map 和 View
import TileLayer from 'ol/layer/Tile'; // 引入瓦片图层
import OSM from 'ol/source/OSM'; // 引入 OpenStreetMap 数据源
import VectorLayer from 'ol/layer/Vector'; // 引入矢量图层
import VectorSource from 'ol/source/Vector'; // 引入矢量数据源
import { Feature } from 'ol'; // 引入要素
import { Point, LineString, Polygon } from 'ol/geom'; // 引入几何类型
import { Style, Fill, Stroke, Circle } from 'ol/style'; // 引入样式


onMounted(() => {


  // 1. 创建地图
  const map = new Map({
    target: 'openLayers-container1', // 地图容器的 ID
    layers: [], // 先不添加任何图层
    view: new View({
      center: [0, 0], // 地图中心坐标
      zoom: 2, // 初始缩放级别
    }),
  });

  // 2. 添加瓦片图层(OpenStreetMap)
  const tileLayer = new TileLayer({
    source: new OSM(), // 使用 OpenStreetMap 作为底图
  });
  map.addLayer(tileLayer);

  // 3. 创建矢量数据源
  const vectorSource = new VectorSource();

  // 4. 创建要素并添加到矢量数据源
  // 点要素
  const pointFeature = new Feature({
    geometry: new Point([0, 0]), // 点的坐标
  });
  pointFeature.setStyle(
    new Style({
      image: new Circle({
        radius: 10, // 点的大小
        fill: new Fill({ color: 'red' }), // 填充颜色
        stroke: new Stroke({ color: 'black', width: 2 }), // 描边
      }),
    })
  );

  // 线要素
  const lineFeature = new Feature({
    geometry: new LineString([
      [-1e6, 1e6], // 起点
      [1e6, 1e6], // 终点
    ]),
  });
  lineFeature.setStyle(
    new Style({
      stroke: new Stroke({
        color: 'blue', // 线的颜色
        width: 3, // 线的宽度
      }),
    })
  );

  // 面要素
  const polygonFeature = new Feature({
    geometry: new Polygon([
      [
        [-1e6, -1e6], // 第一个点
        [1e6, -1e6], // 第二个点
        [1e6, 1e6], // 第三个点
        [-1e6, 1e6], // 第四个点
        [-1e6, -1e6], // 闭合多边形
      ],
    ]),
  });
  polygonFeature.setStyle(
    new Style({
      fill: new Fill({ color: 'rgba(0, 255, 0, 0.5)' }), // 填充颜色
      stroke: new Stroke({ color: 'green', width: 2 }), // 描边
    })
  );

  // 将要素添加到矢量数据源
  vectorSource.addFeatures([pointFeature, lineFeature, polygonFeature]);

  // 5. 创建矢量图层并添加到地图
  const vectorLayer = new VectorLayer({
    source: vectorSource, // 设置矢量数据源
  });
  map.addLayer(vectorLayer);

})
</script>

<style scoped>
#openLayers-container1 {
  width: 100%;
  height: 500px;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

4.投影和坐标系

4.1.投影(Web Mercator)

  • 投影是将地球表面的三维地理坐标(经度、纬度)转换为二维平面坐标的数学方法。
  • 不同的投影适用于不同的场景,例如:
    • EPSG:4326:WGS84 地理坐标系,使用经度和纬度表示位置。
    • EPSG:3857:Web Mercator 投影,广泛用于在线地图(如 Google Maps、OpenStreetMap)。

4.2.坐标系(Coordinate System)

  • 坐标系定义了如何在地图上表示地理数据。
  • OpenLayers 支持多种坐标系,常见的包括:
    • EPSG:4326:WGS84 地理坐标系,单位为度。
    • EPSG:3857:Web Mercator 投影坐标系,单位为米。

4.3.OpenLayers 中的投影使用

  • OpenLayers 默认使用 EPSG:3857(Web Mercator)作为地图的投影。
  • 如果需要使用其他投影(如 EPSG:4326),需要显式设置投影并转换坐标。

4.4.代码示例

vue
<template>
  <div id="openLayers-container2"></div>
</template>

<script setup>
import { onMounted } from 'vue';

import 'ol/ol.css'; // 引入 OpenLayers 的样式
import { Map, View } from 'ol'; // 引入 Map 和 View
import TileLayer from 'ol/layer/Tile'; // 引入瓦片图层
import OSM from 'ol/source/OSM'; // 引入 OpenStreetMap 数据源
import VectorLayer from 'ol/layer/Vector'; // 引入矢量图层
import VectorSource from 'ol/source/Vector'; // 引入矢量数据源
import { Feature } from 'ol'; // 引入要素
import { Point } from 'ol/geom'; // 引入几何类型
import { Style, Circle, Fill, Stroke } from 'ol/style'; // 引入样式
import { fromLonLat, transform } from 'ol/proj'; // 引入投影工具
onMounted(() => {



  // 1. 创建地图
  const map = new Map({
    target: 'openLayers-container2', // 地图容器的 ID
    layers: [], // 先不添加任何图层
    view: new View({
      center: fromLonLat([0, 0]), // 将经纬度坐标转换为 EPSG:3857
      zoom: 2, // 初始缩放级别
    }),
  });

  // 2. 添加瓦片图层(OpenStreetMap)
  const tileLayer = new TileLayer({
    source: new OSM(), // 使用 OpenStreetMap 作为底图
  });
  map.addLayer(tileLayer);

  // 3. 创建矢量数据源
  const vectorSource = new VectorSource();

  // 4. 创建要素并添加到矢量数据源
  // 使用 EPSG:4326 坐标创建点要素
  const pointFeature = new Feature({
    geometry: new Point(fromLonLat([0, 0])), // 将经纬度坐标转换为 EPSG:3857
  });
  pointFeature.setStyle(
    new Style({
      image: new Circle({
        radius: 10, // 点的大小
        fill: new Fill({ color: 'red' }), // 填充颜色
        stroke: new Stroke({ color: 'black', width: 2 }), // 描边
      }),
    })
  );

  // 使用 EPSG:3857 坐标创建点要素
  const pointFeature3857 = new Feature({
    geometry: new Point([0, 0]), // 直接使用 EPSG:3857 坐标
  });
  pointFeature3857.setStyle(
    new Style({
      image: new Circle({
        radius: 10, // 点的大小
        fill: new Fill({ color: 'blue' }), // 填充颜色
        stroke: new Stroke({ color: 'black', width: 2 }), // 描边
      }),
    })
  );

  // 将要素添加到矢量数据源
  vectorSource.addFeatures([pointFeature, pointFeature3857]);

  // 5. 创建矢量图层并添加到地图
  const vectorLayer = new VectorLayer({
    source: vectorSource, // 设置矢量数据源
  });
  map.addLayer(vectorLayer);

  // 6. 动态转换坐标
  // 将 EPSG:4326 坐标转换为 EPSG:3857
  const lonLat = [30, 45]; // 经度 30,纬度 45
  const projectedCoords = fromLonLat(lonLat);
  console.log('EPSG:4326 坐标:', lonLat);
  console.log('转换为 EPSG:3857 坐标:', projectedCoords);

  // 将 EPSG:3857 坐标转换为 EPSG:4326
  const originalCoords = transform(projectedCoords, 'EPSG:3857', 'EPSG:4326');
  console.log('转换回 EPSG:4326 坐标:', originalCoords);


})
</script>

<style scoped>
#openLayers-container2 {
  width: 100%;
  height: 500px;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

代码说明

1投影转换:
  • 使用 fromLonLat 将 EPSG:4326 坐标(经度、纬度)转换为 EPSG:3857 坐标。
  • 使用 transform 将 EPSG:3857 坐标转换回 EPSG:4326 坐标。
2要素创建:
  • 创建了两个点要素,一个使用 EPSG:4326 坐标,另一个使用 EPSG:3857 坐标。
  • 通过 Style 设置要素的样式。
3地图视图:
  • 地图的初始中心坐标通过 fromLonLat 转换为 EPSG:3857 坐标。
4控制台输出:
  • 在控制台中打印坐标转换的结果,方便调试。

5.视图(View)和控制器(Controls)

5.1. 视图(View)

  • 视图定义了地图的显示范围、中心点、缩放级别和旋转角度等属性。

  • 通过视图,可以控制地图的初始状态以及动态调整地图的显示。

  • 主要属性:

    • center:地图的中心坐标。

    • zoom:地图的缩放级别。

    • rotation:地图的旋转角度(以弧度为单位)。

    • projection:地图的投影(默认为 EPSG:3857)。

5.2. 控制器(Controls)

  • 控制器是地图上的交互工具,用于增强用户体验。

  • OpenLayers 提供了多种内置控制器,例如:

    • 缩放控件(Zoom Control):用于放大和缩小地图。

    • 旋转控件(Rotate Control):用于旋转地图。

    • 全屏控件(FullScreen Control):用于全屏显示地图。

    • 比例尺控件(ScaleLine Control):显示地图比例尺。

  • 控制器可以自定义或禁用。

5.3.示例代码:使用视图和控制器

以下代码展示了如何在 OpenLayers 中配置视图和添加控制器。

vue
<template>
  <div id="openLayers-container3"></div>
</template>

<script setup>
import { onMounted } from 'vue';

import 'ol/ol.css'; // 引入 OpenLayers 的样式
import { Map, View } from 'ol'; // 引入 Map 和 View
import TileLayer from 'ol/layer/Tile'; // 引入瓦片图层
import OSM from 'ol/source/OSM'; // 引入 OpenStreetMap 数据源
import { defaults as defaultControls, Zoom, Rotate, FullScreen, ScaleLine } from 'ol/control'; // 引入控制器

onMounted(() => {

  // 1. 创建地图
  const map = new Map({
    target: 'openLayers-container3', // 地图容器的 ID
    layers: [
      new TileLayer({
        source: new OSM(), // 使用 OpenStreetMap 作为底图
      }),
    ],
    view: new View({
      center: [0, 0], // 地图中心坐标(EPSG:3857)
      zoom: 2, // 初始缩放级别
      rotation: Math.PI / 6, // 旋转 30 度(以弧度为单位)
    }),
    controls: defaultControls().extend([
      new Zoom(), // 添加缩放控件
      new Rotate(), // 添加旋转控件
      new FullScreen(), // 添加全屏控件
      new ScaleLine(), // 添加比例尺控件
    ]),
  });

  // 2. 动态调整视图
  const view = map.getView();
  view.on('change:resolution', () => {
    console.log('当前缩放级别:', view.getZoom());
  });

  view.on('change:rotation', () => {
    console.log('当前旋转角度:', view.getRotation());
  });

  // 3. 添加自定义控件
  const customControl = document.createElement('div');
  customControl.className = 'ol-control custom-control';
  customControl.innerHTML = '<button>自定义控件</button>';
  customControl.addEventListener('click', () => {
    alert('你点击了自定义控件!');
  });

  map.addControl(
    new ol.control.Control({
      element: customControl,
    })
  );


})
</script>

<style scoped>
#openLayers-container3 {
  width: 100%;
  height: 500px;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

京ICP备2024093538号-1