共计 5461 个字符,预计需要花费 14 分钟才能阅读完成。
前言
好久不见,间隔 OpenLayers 入门第一篇曾经过了很久,为什么迟迟没有后续呢,次要有两个起因,一是因为近期我的项目里应用地图的局部比拟少,二是因为很多时候即便性能做进去了,然而还是不能齐全了解,不是很明确的货色除了贴代码之外也写不了啥,其实第一篇也是很根底很简略的,然而意外的是看的人是最多的,这让我意识到可能即便是贴一下代码对一些人也是有帮忙的,这就是这一篇的次要目标,可能有一些中央会看不懂,然而不要问,问我也不晓得,如果你恰好理解的话非常欢送在评论里分享,感激~
首先来分享一个我无心中找到的教程,http://linwei.xyz/ol3-primer/index.html。尽管是基于 v3 版本介绍的,很多 api 可能变了,但还是值得一看,除了 OpenLayers 自身的介绍,还会有一些天文基础知识的分享,这种绝对全面的中文教程真的很罕见,且看且珍惜。
接下来分享一些罕用的在线地图瓦片资源:
1. 高德瓦片,最大反对放大到 20 级,字体比拟大,然而最近如同又只能到 19 级了。
http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7
2. 高德瓦片,最大反对放大到 20 级,色彩偏灰绿色。
http://webst0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}
3. 高德瓦片,最大反对放大到 18 级,最罕用的款式。
http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8
4. 谷歌地图瓦片,最大反对放大到 22 级,色彩偏绿色。
https://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}
绘制多边形
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 为多边形每个点的经纬度坐标数组,[[120.11997452699472, 30.314227730637967],[120.11997452699472, 30.314227730637967],...] | |
function renderArea (data) { | |
// 创立因素 | |
const features = [ | |
new Feature({geometry: new Polygon([data])// 应用多边形类型 | |
}) | |
] | |
// 创立矢量数据源 | |
const source = new VectorSource({features}) | |
// 创立款式 | |
const style = new Style({ | |
stroke: new Stroke({ | |
color: '#4C99F8', | |
width: 3, | |
lineDash: [5] | |
}), | |
fill: new Fill({color: 'rgba(255,255,255,0.1)' | |
}) | |
}) | |
// 创立矢量图层 | |
const areaLayer = new VectorLayer({ | |
source, | |
style, | |
zIndex: 1 | |
}) | |
// 增加到地图实例 | |
map.addLayer(areaLayer) | |
} |
多边形的绘制很简略,应用几何类型里的多边形类创立一个因素就能够了。
区域两头的名字显示能够通过 Overlay
叠加层来显示,次要是要计算一下显示的地位:
import Overlay from 'ol/Overlay'; | |
import {boundingExtent} from 'ol/extent'; | |
import {getCenter} from 'ol/extent'; | |
import {fromLonLat} from 'ol/proj'; | |
// 获取一个多边形的四个边界点,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)]; | |
} | |
// 也能够间接应用工具办法:boundingExtent | |
function getExtent (data) {return boundingExtent(data) | |
} | |
// 获取范畴的中心点坐标 | |
let center = getCenter(getExtent(data)); | |
// 显示名称 | |
let nameEl = document.createElement('div') | |
nameEl.className = 'name' | |
nameEl.innerHTML = '我是名称' | |
let nameOverlay = new Overlay({position: fromLonLat(center, 'EPSG:4326'), | |
element: nameEl, | |
offset: [0, 0], | |
positioning: 'bottom-center' | |
}) | |
map.addOverlay(nameOverlay) |
绘制以米为单位的圆
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' | |
// 两种形式 | |
// 1. 应用 circular 绘制 | |
function renderRangeUseCircular (center, radius) {const features = [] | |
features.push(new Feature({geometry: circular(center, radius) | |
})) | |
return new VectorSource({features}) | |
} | |
// 2. 应用 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 | |
} | |
// 绘制 | |
function renderRange () {const source = renderRangeUseCircle(...params) | |
// const source = renderRangeUseCircular(...params) | |
const style = new Style({ | |
stroke: new Stroke({ | |
color: '#4C99F8', | |
width: 3, | |
lineDash: [5] | |
}), | |
fill: new Fill({color: 'rgba(76,153,248,0.3)' | |
}) | |
}) | |
rangeLayer = new VectorLayer({ | |
source, | |
style, | |
zIndex: 2 | |
}) | |
map.addLayer(rangeLayer) | |
} |
绘制圆有两种形式,别离是应用 circular
和Circle
这两者有什么区别我也不太分明,它们的入参根本一样,中心点和半径,文档上没有指出半径的单位,第二种办法是百度上搜到的,绘制完经测距测试后是精确的。
增加暗影成果
OpenLayers 的款式对象并不反对间接设置暗影成果,所以须要获取到 canvas 的绘图上下文来自行添加,原理是监听图层的 prerender
(在一个图层渲染前触发)和postrender
(在一个图层渲染后触发) 事件,批改
canvas` 上下文的绘图款式,对整个图层都是有影响的,所以最好把要增加暗影的因素放到一个独自的图层里:
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(33,150,243,0.20)' | |
}) | |
}) | |
let vectorLayer = new VectorLayer({ | |
source, | |
style | |
}) | |
// 增加暗影 | |
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) |
绘制带边框的线段
OpenLayers 是不间接反对这种带边框的线段的,所以一种简略的办法是绘制两条线段叠加起来,下面的宽度比上面的低,就有边框成果了:
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' | |
// 创立多边形 | |
const features = [ | |
new Feature({geometry: new Polygon([]), | |
}) | |
] | |
// 上层线段,用来做边框,宽度更宽 | |
const source = new VectorSource({features}) | |
const style = new Style({ | |
stroke: new Stroke({ | |
color: '#53AA08', | |
width: 8 | |
}), | |
fill: new Fill({color: 'rgba(151,255,201,0.23)' | |
}) | |
}) | |
areaLayer = new VectorLayer({ | |
source, | |
style, | |
zIndex: 1 | |
}) | |
map.addLayer(areaLayer) | |
// 下层线段,用来做两头局部,宽度较小 | |
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) |
本次分享就这么多了,下次见~