Openlayers开发实战

Openlayers开发实战

2020年08月31日 阅读:318 字数:1212 阅读时长:3 分钟

Openlayers加载在线地图,画点、线、面、图片、自定义切图等数据源,大数据下的聚合标注,绘制交互等

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
})

推荐阅读

恰饭区

评论区 (0)

0/500

还没有评论,快来抢第一吧