Начало работы с OpenLayers (1)

JavaScript

Введение в OpenLayers

Открытые слои (openlayers.org/) — это высокопроизводительная, многофункциональная библиотека JavaScript, используемая для помощи в разработке приложений веб-карт, которые могут удовлетворить практически все потребности в разработке карт.

Имеет следующие характеристики:

  1. Поддерживает любые тайловые ресурсы XYZ, а также стандартный тайловый сервис OGC WMTS и стандартный тайловый сервис ArcGIS.
  2. Поддержка векторных разделов, включая форматы PBF, Geojson, Topojson
  3. Поддерживает векторные слои и может отображать векторные данные в форматах GeoJSON, TopoJSON, KML, GML и других.
  4. Поддержка спецификаций сетевых сервисов ГИС, таких как WMS и WFS, сформулированных OGC.
  5. Поддерживает работу на мобильных устройствах
  6. Вы можете стилизовать управление картой через css
  7. Объектно-ориентированная разработка, все является объектом в OpenLayers

В отличие от leaflet, другой популярной библиотеки карт, openLayers полностью разработана объектно-ориентированным способом, и почти все функции, необходимые для разработки карты, встроены, в то время как основная библиотека leaflet предоставляет только основные функции, а другие функции выполняются через третьи. -сторонние плагины.расширение. С точки зрения использования, с листовки легче начать, а с OpenLayers сложнее, поэтому рекомендуется использовать листовку, если бизнес предсказуем и проще.

Хотя OpenLayers очень мощный, его очень сложно использовать, потому что все является объектом, и он крайне недружелюбен к новичкам из-за крайне уродливой документации. о реальном сценарии развития бизнеса. Некоторый контент, чтобы помочь новичкам использовать OpenLayers.

Это первая часть этой серии, которая в основном знакомит с созданием карт и операциями с базовыми элементами и будет обновляться нерегулярно в будущем.

Эта статья основана на OpenLayers v6+, а код основан на Vue.

Установить

npm i ol

конкретизированная карта

Чтобы отобразить базовую карту, вам сначала нужно предоставить контейнер, установить ширину и высоту, а затем ввести OpenLayers для добавления слоя карты.Картографический сервис может использовать встроенный OSM карты с открытым исходным кодом, или вы можете использовать другие онлайн-сервисы. службы плитки, такие как: Baidu, AutoNavi, Tiantu, Bing, Google и т. д. Конкретным адресом службы может быть Baidu. В этой статье используются службы AutoNavi. Для получения подробной информации см.:у-у-у. Краткое описание.com/afraid/oh 34 85029….

<div class="ol-map" ref="olMap"></div>
import Map from 'ol/Map'
import View from 'ol/View'
import { Tile as TileLayer } from 'ol/layer'
import {XYZ, OSM} from 'ol/source'
import { fromLonLat } from 'ol/proj'

// fromLonLat方法能将坐标从经度/纬度转换为其他投影

// 使用内置的OSM
//const tileLayer = new TileLayer({
//    source: new OSM()
//})
// 使用高德
const tileLayer = new TileLayer({
    source: new XYZ({
        url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
    })
})
let map = new Map({
    layers: [tileLayer],
    view: new View({
        center: fromLonLat([120.771441, 30.756433]),//地图中心点
        zoom: 15,// 缩放级别
        minZoom: 0,// 最小缩放级别
        maxZoom: 18,// 最大缩放级别
        constrainResolution: true// 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
    }),
    target: this.$refs.olMap// DOM容器
})

Это отобразит базовую карту:

Вы можете перетаскивать и масштабировать, но не вращать. Если вам нужно поддерживать вращение, вам нужно добавить взаимодействие с вращением:

import {
  defaults as defaultInteractions,
  DragRotateAndZoom,
} from 'ol/interaction'

let map = new Map({
    // ...
    interactions: defaultInteractions().extend([new DragRotateAndZoom()])
})

Это позволяет вращать карту с помощью мыши, удерживая нажатой клавишу Shift.

OpenLayers имеет множество встроенных готовых элементов управления, которые обычно используются следующим образом:

import { defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control'

let map = new Map({
    // ...
    controls: defaults().extend([
        new FullScreen(), // 全屏
        new MousePosition(), // 显示鼠标当前位置的经纬度
        new ScaleLine()// 显示比例尺
    ])
})

На карте также есть много событий. Вы можете прослушивать необходимые события для выполнения соответствующих операций. Используйте следующее:

map.on('moveend', e => {
    // console.log('地图移动', e)
})
map.on('rendercomplete', () => {
    // console.log('渲染完成')
})
map.on('click', e => {
    // console.log('地图点击', e)
})

Карта отображения в основном находится здесь, а затем давайте рассмотрим некоторые распространенные сценарии использования.

Показать функции

Отображение некоторых пользовательских элементов на карте можно назвать самым основным и распространенным требованием.Если структура или стиль отображаемых элементов сложны, вы можете использовать Overlay, который может отображать элементы DOM на карте и будет сопровождаться по карте двигаться.

import Overlay from 'ol/Overlay'

// 你可以给元素添加任意的内容或属性或样式,也可以给元素绑定事件
let el = document.createElement('div')
let marker = new Overlay({
    element: el,// 要显示的元素
    position: fromLonLat([longitude, latitude], 'EPSG:4326'),// 地图投影的位置
    offset: [-17, -17], // 元素显示的像素偏移量
    autoPan: true, // 自动移动地图以完整的显示元素
})
// 添加到地图
map.addOverlay(marker)
// 从地图上删除
map.removeOverlay(marker)

Если вам нужно использовать элемент векторного объекта для отображения маленького значка, многоугольника, линии и т. д., сначала посмотрите, как отобразить значок изображения:

import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
import { Style, Icon } from 'ol/style'

// 实例化要素
let feature = new Feature({
    geometry: new Point([120.12636255813723, 30.313142215804806])// 地理几何图形选用点几何
})
// 如果需要给要素附加一些自定义数据
feature.set('data', data)
// 设置样式,这里就是显示一张图片icon
feature.setStyle([
    new Style({
        image: new Icon({
          anchor: [0.5, 1],// 显示位置
          size: [18, 28],// 尺寸
          src: require('../../assets/images/mouse_location_ing.png')// 图片url
        })
    })
])
// 矢量源
let source = new VectorSource({
    features: [feature]
})
// 实例化的时候也可以不添加feature,后续通过方法添加:source.addFeatures([feature])
// 清空feature:source.clear()

// 矢量图层
let vector = new VectorLayer({
    source: source
})
// 样式除了可以设置在单个feature上,也可以统一设置在矢量图层上
/*
let vector = new VectorLayer({
    source: source,
    style: new Style({
        image: new Icon({
          anchor: [0.5, 1],// 显示位置
          size: [18, 28],// 尺寸
          src: require('../../assets/images/mouse_location_ing.png')// 图片url
        })
    })
})
*/
map.addLayer(vector)

В приведенном выше примере реализовано добавление элемента значка на карту. Если вы хотите добавить более одного элемента, рекомендуется создать несколько объектов. Эффект будет следующим:

Иногда также необходимо поддерживать перетаскивание объекта для изменения его положения.Для этого требуется поддержка взаимодействия «Перевести»:

import {Translate} from 'ol/interaction'
// ...

// ...
let translate = new Translate({
    layers: [vector]
})
map.addInteraction(translate)
// 可以监听一下拖动开始和结束的事件,拖动后的经纬度可以从e里面获取
translate.on('translateend', (e) => {
    console.log(e)
})
translate.on('translatestart', (e) => {
    console.log(e)
})

Помимо отображения его непосредственно на карте, вы также можете добавить его самостоятельно, то есть добавить элемент в том месте, где щелкает мышь, что требует использования взаимодействия Draw:

import { Draw } from 'ol/interaction'

let draw = new Draw({
    source: source,
    type: 'Point',
    style: new Style({
        image: new Icon({
          anchor: [0.5, 1],// 显示位置
          size: [18, 28],// 尺寸
          src: require('../../assets/images/mouse_location_ing.png')// 图片url
        })
    })
})
// 监听完成事件
draw.on('drawend', (e) => {
    console.log(e)
    // 如果只需要放置一个的话可以移除该交互,否则可以一直添加
    map.removeInteraction(draw)
    
})
map.addInteraction(draw)

Потому что если значков слишком много, я не знаю, что из себя представляет значок, поэтому мне часто нужно добавить всплывающую подсказку к значку, которая отображается при перемещении мыши вверх.Наложение, вы можете использовать его для достижения, пожалуйста видеть:

<!--可以给元素设置一些样式-->
<div class="ol-popup" ref="olPopup">{{olPopupText}}</div>
import Overlay from 'ol/Overlay'

// 创建Overlayer
this.tooltipOverlay = new Overlay({
    element: this.$refs.olPopup,
    positioning: 'bottom-center',// 根据position属性的位置来进行相对点位
    offset: [0, -30],// 在positioning之上再进行偏移
    autoPan: true
})
map.addOverlay(this.tooltipOverlay)

// 给地图绑定鼠标移动事件,检测鼠标位置所在是否存在feature,如果是目标feature的话就显示tooltip
map.on('pointermove', (e) => {
    this.olPopupText = ''
    map.forEachFeatureAtPixel(e.pixel, (f, layer) => {
        if (layer !== this.vectorLayer || !f.get('data')) {
            return false
        }
        this.olPopupText = f.get('data')
        this.tooltipOverlay.setPosition(f.getGeometry().getCoordinates())
    })
})

Это будет отображать всплывающую подсказку при перемещении мыши вверх:

Далее давайте посмотрим, как рисовать многоугольники и рисовать графику, используя предыдущее взаимодействие Draw:

import { Draw } from 'ol/interaction'

let source = new VectorSource()
let vector = new VectorLayer({
    source: source
})
map.addLayer(vector)
let draw = new Draw({
    source: source,
    type: 'Circle'
})
map.addInteraction(draw)

Это очень просто, создайте экземпляр объекта Draw и установите тип.Вышеупомянутая настройка — Circle, и круг рисуется:

Затем посмотрите на квадраты и прямоугольники, измененные поверх приведенного выше примера:

import { createRegularPolygon, createBox } from 'ol/interaction/Draw'

// createRegularPolygon方法执行后返回一个创建正方形的geometryFunction
// createBox方法执行后返回一个创建长方形的geometryFunction

let draw = new Draw({
    source: source,
    type: 'Circle',//没错,还是Circle
    geometryFunction: createBox()
})

Для других типов вам нужно только установить соответствующий тип.Например, чтобы нарисовать неправильный многоугольник как POLYGON, вы можете проверить документ для определенного типа:openlayers.org/en/latest/ аааа….

В реальном сценарии использования будут ситуации, когда существующие полигоны необходимо изменить, и необходимо использовать взаимодействие Modify:

import { Modify } from 'ol/interaction'

let modify = new Modify({
    source
})
map.addInteraction(modify)

Теперь можно перетаскивать конечные точки многоугольника, чтобы изменить его.

Вышеупомянутые операции и отображение геометрии используют стили по умолчанию, которые поставляются с ними. Если у вас есть требования к пользовательскому стилю, вы можете изменить их с помощью конфигурации стиля. Основное использование элементов здесь.

Получить экстент текущей области карты

Из соображений производительности, если вы отображаете элементы на карте, лучше всего отображать элементы только в текущей области отображения.Отображаемые данные обычно запрашиваются из бэкэнда, затем диапазон текущей области может быть отправлен на бэкенд, и только бэкенд. Просто верните данные в этой области, тогда вам нужно получить текущий диапазон:

// 获取当前地图区域上下左右四个点的经纬度
let range = map.getView().calculateExtent(map.getSize())
let state = {
    minLon: range[0],
    minLat: range[1],
    maxLon: range[2],
    maxLat: range[3],
    zoomLevel: map.getView().getZoom()// 当前缩放级别,缩放级别可用来判断是否要将要素聚合进行显示
}

до свидания

Поскольку я только начинаю, могут быть некоторые неправильные места или есть несколько лучших способов реализовать это. Добро пожаловать, чтобы указать.