Blog: lxqnsys.com Official account: Ideal Youth Laboratory

preface

OpenLayers into the shade of a long time no see, distance has been for a long time, why delayed follow-up, there are two main reasons, one is because of the recent projects using part of the map is less, because most of the time even if function to come, but still can’t fully understand, is not very understand the things in addition to the posted code can write what, Actually basis first article also is very simple, but surprise to see who is the most, it made me realize that might even put the code also be helpful for some people, this is the main purpose of this article, there may be some places will look not to understand, but don’t ask, ask me and I don’t know, if you happen to know quite welcome to share in the comments, thank you ~

Let’s start by sharing a tutorial I stumbled across, linwei.xyz/ol3-primer/… . Although the introduction is based on v3 version, many of the APIS may have changed, but it is still worth checking out. In addition to the introduction of OpenLayers itself, there will also be some geography basics to share. This relatively comprehensive Chinese tutorial is really rare, to watch and cherish.

Here are some common online resources for map tiles:

1. Gaudal tiles can be enlarged up to 20 levels with large fonts, but it seems that only 19 levels can be reached recently.

http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7
Copy the code

2. Gaode tiles, maximum support to 20 levels, color grayish green.

http://webst0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}
Copy the code

3. Gode tiles, support up to 18 levels, the most commonly used style.

http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8
Copy the code

4. Google Maps tiles, up to 22 levels supported, green color.

https://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}
Copy the code

Draw polygons

import Feature from 'ol/Feature'
import Polygon from 'ol/geom/Polygon'
import { Vector as VectorSource } from 'ol/source'
import { Style, Stroke, Fill } from 'ol/style'
import { Vector as VectorLayer } from 'ol/layer'

// Data is the latitude and longitude coordinate array of each polygon point,[[120.11997452699472, 30.314227730637967],[120.11997452699472, 30.314227730637967],...
function renderArea (data) {
    // Create elements
    const features = [
        new Feature({
            geometry: new Polygon([data])// Use the polygon type})]// Create a vector data source
    const source = new VectorSource({
        features
    })
    // Create a style
    const style = new Style({
        stroke: new Stroke({
            color: '#4C99F8'.width: 3.lineDash: [5]}),fill: new Fill({
            color: 'rgba (255255255,0.1)'})})// Create vector layers
    const areaLayer = new VectorLayer({
        source,
        style,
        zIndex: 1
    })
    // Add to map instance
    map.addLayer(areaLayer)
}
Copy the code

Polygon drawing is simple, using the polygon class of the geometry type to create an element.

An Overlay layer is used to display the name in the middle of an Overlay area.

import Overlay from 'ol/Overlay';
import { boundingExtent } from 'ol/extent';
import { getCenter } from 'ol/extent';
import { fromLonLat } from 'ol/proj';

// Get four boundary points of a polygon, data:[[120.11997452699472, 30.314227730637967],[120.11997452699472, 30.314227730637967],...
function getExtent (data) {
    let minx = 99999999;
    let miny = 99999999;
    let maxx = -99999999999;
    let maxy = -99999999999;
    data.forEach((item) = > {
        if (item[0] > maxx) {
            maxx = item[0];
        }
        if (item[0] < minx) {
            minx = item[0];
        }
        if (item[1] > maxy) {
            maxy = item[1];
        }
        if (item[1] < miny) {
            miny = item[1]; }});return [Number(minx), Number(miny), Number(maxx), Number(maxy)];
}
// The utility method boundingExtent can also be used directly
function getExtent (data) {
    return boundingExtent(data)
}
// Get the center coordinates of the range
let center = getCenter(getExtent(data));
// Display the name
let nameEl = document.createElement('div')
nameEl.className = 'name'
nameEl.innerHTML = 'I am the name'
let nameOverlay = new Overlay({
    position: fromLonLat(center, 'EPSG:4326'),
    element: nameEl,
    offset: [0.0].positioning: 'bottom-center'
})
map.addOverlay(nameOverlay)
Copy the code

Draw a circle in meters

import Feature from 'ol/Feature'
import { circular } from 'ol/geom/Polygon'
import { Vector as VectorSource } from 'ol/source'
import { getPointResolution } from 'ol/proj'
import { METERS_PER_UNIT } from 'ol/proj/Units'
import Circle from 'ol/geom/Circle'
import { Style, Stroke, Fill } from 'ol/style'
import { Vector as VectorLayer } from 'ol/layer'

// Two ways

// 1. Draw circular
function renderRangeUseCircular (center, radius) {
    const features = []
    features.push(new Feature({
        geometry: circular(center, radius)
    }))
    return new VectorSource({
        features
    })
}

// 2. Use Circle to draw a Circle
function renderRangeUseCircle (center, projection = 'EPSG:4326', radius) {
    const view = map.getView()
    const resolutionAtEquator = view.getResolution()
    const pointResolution = getPointResolution(projection, resolutionAtEquator, center, METERS_PER_UNIT.m)
    const resolutionFactor = resolutionAtEquator / pointResolution
    radius = (radius / METERS_PER_UNIT.m) * resolutionFactor
    const circle = new Circle(center, radius)
    const circleFeature = new Feature(circle)
    const vectorSource = new VectorSource({
        projection: projection
    })
    vectorSource.addFeature(circleFeature)
    return vectorSource
}

/ / to draw
function renderRange () {
    constsource = renderRangeUseCircle(... params)// const source = renderRangeUseCircular(... params)
    const style = new Style({
        stroke: new Stroke({
            color: '#4C99F8'.width: 3.lineDash: [5]}),fill: new Fill({
            color: 'rgba (76153248,0.3)'
        })
    })
    rangeLayer = new VectorLayer({
        source,
        style,
        zIndex: 2
    })
    map.addLayer(rangeLayer)
}
Copy the code

There are two ways to draw circles, namely, circular and Circle. I’m not sure what the difference is between them. Their input parameters are basically the same, including center point and radius, and the unit of radius is not indicated in the document.

Add shadow effect

The OpenLayers style object does not support setting shadow effects directly, so you need to get the canvas’s drawing context to add them by listening for prerender and Postrender events on layers. Changing the drawing style of the Canvas context affects the entire layer, so it is best to put the elements to be shaded on a separate layer:

import { Vector as VectorSource } from 'ol/source'
import { Style, Stroke, Fill } from 'ol/style'
import { Vector as VectorLayer } from 'ol/layer'

const source = new VectorSource({
    features: []})const style = new Style({
    stroke: new Stroke({
        color: '#437AF6'.width: 2
    }),
    fill: new Fill({
        color: 'rgba (33150243,0.20)'})})let vectorLayer = new VectorLayer({
    source,
    style
})
// Add a shadow
vectorLayer.on('prerender'.evt= > {
    evt.context.shadowBlur = 4
    evt.context.shadowColor = 'rgba (0,0,0,0.20)'
})
vectorLayer.on('postrender'.evt= > {
    evt.context.shadowBlur = 0
    evt.context.shadowColor = 'rgba (0,0,0,0.20)'
})
map.addLayer(vectorLayer)
Copy the code

Draws a line segment with borders

OpenLayers does not support this type of line segment directly, so an easy way to create a border effect is to draw two line segments stacked together, with the width of the top lower than the bottom:

import Polygon from 'ol/geom/Polygon'
import Feature from 'ol/Feature'
import { Vector as VectorSource } from 'ol/source'
import { Style, Stroke, Fill } from 'ol/style'
import { Vector as VectorLayer } from 'ol/layer'

// Create a polygon
const features = [
    new Feature({
        geometry: new Polygon([]),
    })
]

// Lower line segment, used for border, width wider
const source = new VectorSource({
    features
})
const style = new Style({
    stroke: new Stroke({
        color: '#53AA08'.width: 8
    }),
    fill: new Fill({
        color: 'rgba (151255201,0.23)'
    })
})
areaLayer = new VectorLayer({
    source,
    style,
    zIndex: 1
})
map.addLayer(areaLayer)

// Upper line segment, used for middle part, smaller width
const source2 = new VectorSource({
    features
})
const style2 = new Style({
    stroke: new Stroke({
        color: '#2AE000'.width: 2
    })
})
areaLayer2 = new VectorLayer({
    source: source2,
    style: style2,
    zIndex: 2
})
map.addLayer(areaLayer2)
Copy the code

That’s all for this time. See you next time