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