openlayers使用相关

英文能力好的,可以直接去扒拉官网!!!

官网地址: https://openlayers.org/
快速开始: https://openlayers.org/doc/quickstart.html

地图相关模块

Map

The map is the core component of OpenLayers. For a map to render, a view, one or more layers, and a target container are needed(地图是OpenLayers的核心组件。要呈现一个地图,需要一个视图、一个或多个图层和一个目标容器):

import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import OSM from 'ol/source/OSM.js';

const map = new Map({
  // view
  view: new View({
    center: [0, 0],
    zoom: 1,
  }),
  // one or more layers
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
  ],
  // a target container
  target: 'map',
});

view

A View object represents a simple 2D view of the map.
This is the object to act upon to change the center, resolution, and rotation of the map.(这是用于更改地图的中心、分辨率和旋转的对象。)

Layers (图层)

TileLayer (瓦片图层)

For layer sources that provide pre-rendered, tiled images in grids that are organized by zoom levels for specific resolutions. Note that any property set in the options is set as a BaseObject property on the layer object; for example, setting title: ‘My Title’ in the options means that title is observable, and has get/set accessors.
(对于在网格中提供预渲染平铺图像的图层源,这些网格按特定分辨率的缩放级别组织。注意,在选项中设置的任何属性都被设置为层对象的BaseObject属性;例如,在options中设置title: 'My title '意味着title是一个可观察对象,并且有get/set访问器。)

ImageLayer(图像图层)

Server-rendered images that are available for arbitrary extents and resolutions.
(可用于任意范围和分辨率的服务器渲染图像)

VectorLayer(矢量图层)

Vector data is rendered client-side, as vectors. This layer type provides most accurate rendering even during animations. Points and labels stay upright on rotated views. For very large amounts of vector data, performance may suffer during pan and zoom animations. In this case, try VectorImageLayer.
(矢量数据在客户端呈现为矢量。即使在动画期间,此图层类型也能提供最准确的渲染。点和标签在旋转视图上保持直立。对于大量矢量数据,平移和缩放动画期间性能可能会受到影响。在这种情况下,请尝试VectorImageLayer。)

VectorImageLayer(矢量图像图层)

Vector data is rendered client-side, to an image. This layer type provides great performance during panning and zooming, but point symbols and texts are always rotated with the view and pixels are scaled during zoom animations. For more accurate rendering of vector data, use VectorLayer instead.
(矢量数据在客户端渲染为图像。此图层类型在平移和缩放期间提供了出色的性能,但点符号和文本始终随视图旋转,并且像素在缩放动画期间缩放。为了更准确地渲染矢量数据,请改用 VectorLayer。)

VectorTileLayer (矢量瓦片图层)

Layer for vector tile data that is rendered client-side.(客户端渲染的矢量切片数据的图层。)

WebGLTileLayer (WebGL瓦片图层)

For layer sources that provide pre-rendered, tiled images in grids that are organized by zoom levels for specific resolutions.(对于在网格中提供预渲染、平铺图像的图层源,这些图像按特定分辨率的缩放级别进行组织。)

vue3中使用

安装

pnpm add ol

简单使用

<template>
 <div id="weather-map" />
</template>
<script setup lang="ts">
  import { ref, reactive } from 'vue'
  import 'ol/ol.css'
  import TileLayer from 'ol/layer/Tile'
  import { Map, View } from 'ol'
  import { fromLonLat } from 'ol/proj'
  import XYZ from 'ol/source/XYZ'

  /** 地图相关操作 */
  const map = ref()
  
  const mapView = reactive({
    center: fromLonLat([116.397128, 39.916527]), // 北京
    zoom: 10,
    minZoom: 4,
    maxZoom: 18
  })

  const mapUrl = ref(
    'http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=97546c3d85ab8620c9459aac2906743b'
  )

  const initMap = () => {
    const tileLayer = new TileLayer({
      opacity: 0.8, // 透明度
      source: new XYZ({
        url: mapUrl.value
      })
    })
    map.value = new Map({
      layers: [tileLayer],
      view: new View(mapView),
      target: 'weather-map'
    })
  }
  const removeMap = () => {
    if (map.value) {
      // handleChangeCheck([]).removeCircleLayer()
      // handleChangeCheck([]).removeImageLayer()
      map.value.dispose()
      map.value = null
    }
  }
</script>
<style lang="scss" scoped>
#weather-map {
  width: 600px;
  height: 400px;
  margin: auto;
}
</style>

业务场景

开发中有一些业务场景,在这记录一下实现,可以参考

1. 绘制多边形或者圆形

import "./style.css";
import { Map, View, Feature } from "ol";
import { Polygon, LineString, Point } from "ol/geom";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Fill, Style, Circle as CircleStyle, Text, Stroke } from "ol/style";

// 创建要素图层
const vectorLayer = new VectorLayer({
  source: new VectorSource({
    features: [
      new Feature({
        geometry: new Polygon([
          [
            [119.0, 29.0],
            [119.2, 29.0],
            [119.2, 29.2],
            [119.0, 29.2],
            [119.0, 29.0],
          ],
        ]),
        name: "A",
      }),
      new Feature({
        geometry: new Polygon([
          [
            [119.4, 29.0],
            [119.6, 29.0],
            [119.5, 29.2],
            [119.4, 29.0],
          ],
        ]),
        name: "B",
      }),
      new Feature({
        geometry: new LineString([
          [119.0, 29.4],
          [119.2, 29.3],
          [119.4, 29.5],
          [119.6, 29.3],
          [119.8, 29.6],
        ]),
        name: "C",
      }),
      new Feature({
        geometry: new Point([119.4, 29.6]),
        name: "D",
      }),
    ],
  }),
  style: new Style({
    image: new CircleStyle({
      radius: 30,
      stroke: new Stroke({
        width: 4,
        color: "red",
      }),
      fill: new Fill({
        color: "pink",
      }),
    }),
    stroke: new Stroke({
      width: 4,
      color: "blue",
    }),
    fill: new Fill({
      color: "yellow",
    }),
    text: new Text({
      font: '10px Microsoft YaHei',
      text: '测试',
      overflow: true,
      textAlign: 'center',
      textBaseline: 'middle',
      fill: new Fill({
        color: '#0e84ba'
      }),
      offsetX: 0
    })
  }),
});

// 创建地图
const map = new Map({
  target: "map",
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
  ],
  view: new View({
    projection: "EPSG:4326",
    center: [119.2, 29.2],
    zoom: 10,
  }),
});
map.addLayer(vectorLayer);

在这里插入图片描述

2. 绘制网格并可框选

2.1 框选实现

参考自:OpenLayers基础教程——要素的点选、框选、圈选、多边形选择

import "./style.css";
import { Map, View, Feature } from "ol";
import { Polygon, LineString, Point } from "ol/geom";
import { Select, DragBox } from "ol/interaction";
import { never, always } from "ol/events/condition";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Fill, Style, Circle as CircleStyle, Text, Stroke } from "ol/style";

// 创建要素图层
const vectorLayer = new VectorLayer({
  source: new VectorSource({
    features: [
      new Feature({
        geometry: new Polygon([
          [
            [119.0, 29.0],
            [119.2, 29.0],
            [119.2, 29.2],
            [119.0, 29.2],
            [119.0, 29.0],
          ],
        ]),
        name: "A",
      }),
      new Feature({
        geometry: new Polygon([
          [
            [119.4, 29.0],
            [119.6, 29.0],
            [119.5, 29.2],
            [119.4, 29.0],
          ],
        ]),
        name: "B",
      }),
      new Feature({
        geometry: new LineString([
          [119.0, 29.4],
          [119.2, 29.3],
          [119.4, 29.5],
          [119.6, 29.3],
          [119.8, 29.6],
        ]),
        name: "C",
      }),
      new Feature({
        geometry: new Point([119.4, 29.6]),
        name: "D",
      }),
    ],
  }),
  style: new Style({
    image: new CircleStyle({
      radius: 30,
      stroke: new Stroke({
        width: 4,
        color: "red",
      }),
      fill: new Fill({
        color: "pink",
      }),
    }),
    stroke: new Stroke({
      width: 4,
      color: "blue",
    }),
    fill: new Fill({
      color: "yellow",
    }),
    text: new Text({
      font: "10px Microsoft YaHei",
      text: "测试",
      overflow: true,
      textAlign: "center",
      textBaseline: "middle",
      fill: new Fill({
        color: "#0e84ba",
      }),
      offsetX: 0,
    }),
  }),
});

// 创建地图
const map = new Map({
  target: "map",
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
  ],
  view: new View({
    projection: "EPSG:4326",
    center: [119.2, 29.2],
    zoom: 10,
  }),
});
map.addLayer(vectorLayer);

// 创建选择工具,用于盛放矩形框内的要素
const select = new Select({
  condition: never,
  style: new Style({
    image: new CircleStyle({
      radius: 30,
      stroke: new Stroke({
        width: 4,
        color: "red",
      }),
      fill: new Fill({
        color: "green",
      }),
    }),
    stroke: new Stroke({
      width: 4,
      color: "red",
    }),
    fill: new Fill({
      color: "green",
    }),
    text: new Text({
      font: "10px Microsoft YaHei",
      text: "测试",
      overflow: true,
      textAlign: "center",
      textBaseline: "middle",
      fill: new Fill({
        color: "#ffffff",
      }),
      offsetX: 0,
    }),
  }),
});

// 创建绘制工具
const dragBox = new DragBox({
  condition: always,
});

// 开始绘制,清除已有要素
dragBox.on("boxstart", function () {
  select.getFeatures().clear();
});

// 结束绘制
dragBox.on("boxend", function () {
  // 获取被选择的要素
  const extent = dragBox.getGeometry().getExtent();
  vectorLayer
    .getSource()
    .forEachFeatureIntersectingExtent(extent, function (feature) {
      select.getFeatures().push(feature);
    });

  // 遍历被选中的要素
  const selected = [];
  const selectedFeatures = select.getFeatures();
  for (let i = 0; i < selectedFeatures.getLength(); i++) {
    const feature = selectedFeatures.item(i);
    const name = feature.get("name");
    selected.push(name);
  }
  // 输出查询结果
  const msg = selected.join("、");
  document.getElementById("msg").innerText = "被选中的要素:" + msg;
});

// 添加交互工具
map.addInteraction(dragBox);
map.addInteraction(select);

在这里插入图片描述

2.2 绘制网格并可框选

在这里插入图片描述
在这里插入图片描述
实现:

import "./style.css";
import { Map, View, Feature } from "ol";
import { Polygon } from "ol/geom";
import { Select, DragBox } from "ol/interaction";
import { never, always } from "ol/events/condition";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Fill, Style, Text, Stroke } from "ol/style";

/**
 * 根据起始点、终止点和步长生成网格
 * @param {Array<number>} startPosition - 左上角经纬度 [经度, 纬度]
 * @param {Array<number>} endPosition - 右下角经纬度 [经度, 纬度]
 * @param {number} lonStep - 经度步长
 * @param {number} latStep - 纬度步长
 * @returns {Array<Feature>} 生成的网格要素数组
 */
const generateGrid = (startPosition, endPosition, lonStep, latStep) => {
  const features = [];
  let idCounter = 1; // 用于给每个长方形赋予一个简单的数字ID,从1开始

  for (let lon = startPosition[0]; lon < endPosition[0]; lon += lonStep) {
    for (let lat = startPosition[1]; lat > endPosition[1]; lat -= latStep) {
      const squareCoords = [
        [
          [lon, lat],
          [lon + lonStep, lat],
          [lon + lonStep, lat - latStep],
          [lon, lat - latStep],
          [lon, lat], // 闭合长方形
        ],
      ];

      const feature = new Feature({
        geometry: new Polygon(squareCoords),
        name: idCounter.toString(), // 将ID转换为字符串作为name
      });

      features.push(feature);
      idCounter++; // 更新ID计数器
    }
  }

  return features;
};

// 使用 generateGrid 函数生成网格并创建 VectorLayer
const vectorSource = new VectorSource({
  features: generateGrid([119.0, 29.2], [119.8, 28.2], 0.4, 0.2),
});

const vectorLayer = new VectorLayer({
  source: vectorSource,
  style: function (feature) {
    // 同原始代码中的样式设置
    return new Style({
      stroke: new Stroke({
        width: 4,
        color: "red",
      }),
      fill: new Fill({
        color: "yellow",
      }),
      text: new Text({
        font: "10px Microsoft YaHei",
        text: feature.get("name"),
        overflow: true,
        textAlign: "center",
        textBaseline: "middle",
        fill: new Fill({
          color: "#0e84ba",
        }),
        offsetX: 0,
      }),
    });
  },
});

// 创建地图
const map = new Map({
  target: "map",
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
  ],
  view: new View({
    projection: "EPSG:4326",
    center: [119.2, 29.2],
    zoom: 10,
  }),
});
map.addLayer(vectorLayer);

// 创建选择工具,用于盛放矩形框内的要素
const select = new Select({
  condition: never,
  style: function (feature) {
    return new Style({
      stroke: new Stroke({
        width: 4,
        color: "red",
      }),
      fill: new Fill({
        color: "green",
      }),
      text: new Text({
        font: "10px Microsoft YaHei",
        text: "选中" + feature.get("name"),
        overflow: true,
        textAlign: "center",
        textBaseline: "middle",
        fill: new Fill({
          color: "#ffffff",
        }),
        offsetX: 0,
      }),
    });
  },
});

// 创建绘制工具
const dragBox = new DragBox({
  condition: always,
});

// 开始绘制,清除已有要素
dragBox.on("boxstart", function () {
  select.getFeatures().clear();
});

// 结束绘制
dragBox.on("boxend", function () {
  // 获取被选择的要素
  const extent = dragBox.getGeometry().getExtent();
  vectorLayer
    .getSource()
    .forEachFeatureIntersectingExtent(extent, function (feature) {
      select.getFeatures().push(feature);
    });

  // 遍历被选中的要素
  const selected = [];
  const selectedFeatures = select.getFeatures();
  for (let i = 0; i < selectedFeatures.getLength(); i++) {
    const feature = selectedFeatures.item(i);
    const name = feature.get("name");
    selected.push(name);
  }
  // 输出查询结果
  const msg = selected.join("、");
  document.getElementById("msg").innerText = "被选中的要素:" + msg;
});

// 监听地图的点击事件,点击时清除框选
map.on("singleclick", function () {
  select.getFeatures().clear();
  document.getElementById("msg").innerText = "";
});

// 添加交互工具
map.addInteraction(dragBox);
map.addInteraction(select);

3. 监听地图的分辨率变化

/** 动态设置内部蓝色圆样式的函数 */
function updateStyleBasedOnResolution(feature, resolution) {
  // resolution分辨率
  const fontSize = Math.round((12 / resolution) * 120)
  const radius = Math.round((10 / resolution) * 100)

  const dynamicLabelStyle = new Style({
    text: new Text({
      text: feature.style_.text_.text_,
      font: `${fontSize}px`,
      fill: new Fill({ color: '#fff' })
    }),
    image: new CircleStyle({
      radius: radius,
      fill: new Fill({ color: '#1D59F2' }),
      stroke: new Stroke({ color: '#1D59F2', width: 2 })
    })
  })
  feature.setStyle(dynamicLabelStyle)
}

// 监听地图的分辨率变化
map.value.getView().on('change:resolution', function() {
  // const resolution = map.value.getView().getResolution()
  // 缩放蓝色圆圈部分
  features.value.forEach((feature, idx) => {
    // if (idx % 2) { updateStyleBasedOnResolution(feature, resolution) }
  })
})

4. 离线瓦片部署

我的天地图在线瓦片资源
http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=97546c3d85ab8620c9459aac2906743b

4.1 瓦片资源下载

一款极速瓦片地图下载器-tiler,支持mapbox矢量瓦片下载。支持谷歌影像、百度地图、高德、天地图、四维、OSM等瓦片地图下载,离线地图soeasy。
在这里插入图片描述
使用chatgpt写了个简单的node统计程序

const fs = require('fs');
const path = require('path');
const colors = require('ansi-colors');

function countJPGFilesInDirectory(directoryPath) {
    let count = 0;

    function traverseDirectory(currentPath) {
        const files = fs.readdirSync(currentPath);

        files.forEach((file, index) => {
            const filePath = path.join(currentPath, file);
            const stats = fs.statSync(filePath);

            if (stats.isDirectory()) {
                traverseDirectory(filePath);
            } else if (path.extname(file).toLowerCase() === '.jpg') {
                count++;
            }

            // 模拟延时效果
            setTimeout(() => {
                const progress = ((index + 1) / files.length * 100).toFixed(2);
                process.stdout.write(`\r${colors.blue('Progress:')} ${colors.green(`${progress}%`)}`);
            }, 50);
        });
    }

    traverseDirectory(directoryPath);

    return count;
}

const directoryPath = '../tianditu/9';
console.log(`Counting JPG files in ${colors.yellow(directoryPath)}...`);
const jpgCount = countJPGFilesInDirectory(directoryPath);
console.log(`\nTotal number of JPG files in ${colors.yellow(directoryPath)} and its subdirectories: ${colors.cyan(jpgCount)}`);

4.2 部署
  1. 本地node服务

    在下载的瓦片文件目录下

    安装

    npm i http-server -g
    

    启动(–cors 解决地图资源跨域)

    http-server --cors
    
  2. nginx代理

    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        server {
            listen 80;
            server_name localhost;
    
            root /usr/share/nginx/html/tianditu/;
            index index.html;
    
            location / {
                try_files $uri $uri/ =404;
            }
    
            location ~* ^/(?<category>[^/]+)/(?<subcategory>[^/]+)/(?<image>[^/]+)$ {
                alias /usr/share/nginx/html/tianditu/$category/$subcategory/$image;
            }
        }
    
    }
    
4.3 使用
const mapUrl = ref(
   'http://127.0.0.1:8080' + '/{z}/{x}/{y}.jpg'
)
  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用Vue3接入OpenLayers时,可以按照以下步骤进行操作: 1. 在Vue项目中安装OpenLayers库。可以通过npm或yarn命令来安装OpenLayers,例如: ``` npm install ol ``` 或 ``` yarn add ol ``` 2. 在需要使用OpenLayersVue组件中,引入OpenLayers相关模块和样式。可以使用import语句来引入需要的模块,例如: ``` import 'ol/ol.css'; import { Map, View, Feature, Polygon } from 'ol'; import { Vector as VectorLayer } from 'ol/layer'; import { Vector as VectorSource } from 'ol/source'; import { Style, Stroke } from 'ol/style'; ``` 3. 在Vue组件的`data`中定义地图容器和其他需要的变量,例如: ``` data() { return { map: null, vectorSource: null, vectorLayer: null }; } ``` 4. 在Vue组件的`mounted`钩子函数中,初始化地图。可以创建地图容器,并设置初始视图和图层,例如: ``` mounted() { this.map = new Map({ target: 'map-container', // 'map-container'是你在模板中定义的地图容器的id view: new View({ center: [0, 0], zoom: 10 }), layers: [ this.vectorLayer // 添加自定义的矢量图层 ] }); } ``` 5. 在需要绘制扇形或环形的地方,使用OpenLayers相关功能进行绘制。可以使用OpenLayers的绘制工具和几何图形对象来实现,例如: ``` // 绘制环形 const circle = new Feature(new Polygon([...])); this.vectorSource.addFeature(circle); // 绘制扇形 const sector = new Feature(new Polygon([...])); this.vectorSource.addFeature(sector); ``` 这里需要根据你的具体需求,创建相应的几何图形对象,并将其添加到矢量图层的数据源中。 6. 最后,不要忘记在组件销毁时清理地图相关资源,例如在Vue组件的`beforeDestroy`钩子函数中: ``` beforeDestroy() { this.map.setTarget(null); this.map = null; this.vectorSource = null; this.vectorLayer = null; } ``` 通过以上步骤,你就可以在Vue3中成功使用OpenLayers进行地图操作,包括加载数据、绘制扇形和环形等功能。请根据你的具体需求进行相应的修改和调整。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值