Openlayers加载在线地图,画点、线、面、图片、自定义切图等数据源,大数据下的聚合标注,绘制交互等
参考 https://openlayers.org/en/latest/examples ,官网更详细
1.初始化
地图初始化,并加载在线地图资源,这里以天地图为例
import { Map, View } from 'ol'
import { Tile } from 'ol/layer'
import { XYZ } from 'ol/source'
const baseLayer = new Tile() // 底图
const labelLayer = new Tile() // 标注
map = new Map({
layers: [baseLayer, labelLayer],
target: Element, // 绑定的dom元素
view: new View({
center: center, // 中心点坐标
maxZoom: maxZoom, // 最大缩放等级
minZoom: minZoom, // 最小缩放等级
zoom: zoom // 默认缩放等级
})
})
getTdtSource(lyr) {
const key = '3d7245b3b701467ef55e80a971c91612' // 当出现418、429状态码,可能是apiKey超出每日调用限制了,换一个或自己注册
const url = 'http://t{0-7}.tianditu.com/DataServer?T=' + lyr + '&X={x}&Y={y}&L={z}&tk=' + key
return new XYZ({
url: url
})
}
/**
* 切换地图瓦片材质
* @param {string} type 默认矢量图
* @example ['影像','地形']
*/
changeBaseLayer(type) {
let baseSource, labelSouce
switch (type) {
case '影像':
{
baseSource = getTdtSource('img_w')
labelSouce = getTdtSource('cia_w')
break
}
case '地形':
{
baseSource = getTdtSource('ter_w')
labelSouce = getTdtSource('cva_w')
break
}
default: // 矢量图
{
baseSource = getTdtSource('vec_w')
labelSouce = getTdtSource('cva_w')
break
}
}
baseLayer.setSource(baseSource)
labelLayer.setSource(labelSouce)
}
2.销毁实例
由于OpenLayers中大量用到了闭包,最开始OpenLayers的内存泄露、销毁问题也是蛮严重的,后面差不多每个类中都写了destroy方法,用于释放资源,在单页应用中,在销毁当前组件前应调用下Openlayers用到那些类的destroy方法以释放资源。
/**
* 销毁openlayers,内存回收
* @summary 移除UI控件、交互、图层、要素、覆盖物
*/
destroy() {
const controls = map.getControls().getArray()
const interactions = =map.getInteractions().getArray()
const layers = map.getLayers().getArray()
const overlays = map.getOverlays().getArray()
for (let i = controls.length - 1; i >= 0; i--) {
map.removeControl(controls[i])
}
for (let i = interactions.length - 1; i >= 0; i--) {
map.removeInteraction(interactions[i])
}
for (let i = layers.length - 1; i >= 0; i--) {
const sources = layers[i].getSource()
if (sources && sources.clear) sources.clear()
map.removeLayer(layers[i])
}
for (let i = overlays.length - 1; i >= 0; i--) {
map.removeOverlay(overlays[i])
}
}
3.画各种要素、数据源
3.1.点
import { Feature } from 'ol'
import { Point } from 'ol/geom'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
const feature = new Feature({
geometry: new Point(coordinates)
})
const pointLayer = new VectorLayer({
source: new VectorSource({
features: [feature]
}),
style: function(feature) {}
})
map.addLayer(pointLayer)
3.2.线
import { Feature } from 'ol'
import { LineString } from 'ol/geom'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
const features = []
for (let i = 0; i < data.length; i++) {
const feature = new Feature({
geometry: new LineString(data[i])
})
features.push(feature)
}
const lineLayer = new VectorLayer({
source: new VectorSource({
features: features
}),
style: function(feature) {}
})
map.addLayer(lineLayer)
3.3.面
import { Feature } from 'ol'
import { Polygon } from 'ol/geom'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
const extent = [x1, y1, x2, y2]
// 多边形要素
const polygonFeature = new Feature(
new Polygon(
[
[
[x1, y1], // 原点
[x1, y2], // 第二个点
[x2, y2], // 第三个点
// ……
[x1, y1] // 回到原点
]
]
)
)
const source = new VectorLayer({
features: [polygonFeature]
})
var polygonLayer = new VectorSource({
source: source,
style: function() {}
})
map.addLayer(polygonLayer)
3.4.单张图片
import { Image as ImageLyaer } from 'ol/layer'
import { ImageStatic } from 'ol/source'
const source = new ImageStatic({
crossOrigin: 'anonymous',
url: img.url, // 图片的地址
imageExtent: [0, 0, 1920, 1080] // 图片的展示范围,无参考坐标系可以用图片的尺寸
})
const tl = new ImageLyaer({
source: source
})
map.addLayer(tl)
4.聚合
import { Feature } from 'ol'
import { Point } from 'ol/geom'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource, Cluster } from 'ol/source'
import { Style, Circle, Stroke, Fill, Text } from 'ol/style'
//此示例创建10000个要素
const count = 10000;
const features = new Array(count);
const e = 4500000;
for(let i = 0; i < count; i++){
const coordinates = [2*e*Math.random()-e, 2*e*Math.random()-e];
features[i] = new Feature(
new Point(coordinates)
);
}
//矢量要素数据源
const source = new VectorSource({
features: features
});
//聚合标注数据源
const clusterSource = new Cluster({
distance: 40, //聚合的距离参数,即当标注间距离小于此值时进行聚合,单位是像素
source: source //聚合的数据源,即矢量要素数据源对象
});
//加载聚合标注的矢量图层
const styleCache = {}; //用于保存特定数量的聚合群的要素样式
const clusters = new VectorLayer({
source: clusterSource,
style: function (feature, resolution){
const size = feature.get('features').length; //获取该要素所在聚合群的要素数量
let style = styleCache[size];
if(!style){
style = [
new Style({
image: new Circle({
radius: 10,
stroke: new Stroke({
color: '#fff'
}),
fill: new Fill({
color: '#3399CC'
})
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff'
})
})
})
];
styleCache[size] = style;
}
return style;
}
});
map.addLayer(clusters);
5.覆盖物
import { Overlay } from 'ol'
/**
* 添加覆盖要素
* @param { HTMLElement | String } 元素id | HTML元素
* @param { String } positioning 容器基于鼠标点的定位
* @param { Array } offset 容器的偏移
*/
addOverLayers(name = 'simpleCarBox', positioning, offset = [0, 0]) {
this.overlay = new Overlay({
id: name,
element: document.getElementById(name),
autoPan: true,
positioning,
offset,
autoPanAnimation: {
duration: 250
}
})
map.addOverlay(this.overlay)
}
/**
* 更新信息气泡的位置
* @param {Array} coordinate 新的坐标点
*/
setOverLayer(coordinates) {
this.overlay.setPosition(coordinates)
}
6.绘制、交互
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
import { Draw, Snap, Modify } from 'ol/interaction'
const drawSource = new VectorSource()
const drawLayer = new VectorLayer({
source: drawSource,
style: function() {}
})
const draw = new Draw({
source: drawSource
})
// 可选中
const snap = new Snap({ source: drawSource })
// 可修改
const modify = new Modify({ source: drawSource })
map.addInteraction(draw)
map.addInteraction(snap)
map.addInteraction(modify)
map.addLayer(drawLayer)
7.导出图片
获取map中的canvas,并导出图片
map.once('postcompose', (event) => {
const canvas = event.context.canvas
const imageData = canvas.toDataURL('image/png')
return imageData
})
还没有评论,快来抢第一吧