Open Layers 独立组件,在实际 Vue 项目中直接复制粘贴即可使用,并根据自身需求开启对应图案绘制方法,也可以设置点击按钮作为绘制方式切换,此次需求未设计不做开发。

因为是在 Vue 项目中创建的组件,所以需要引入 Vue-cli 以及 ol 组件,详细创建方式可见vue+openlayers : 从0 到1 搭建开发环境​​​​​​

 如果只做测试,建议在 Vue-cli 项目的 App.vue 文件中直接引入,并注释自带的样式,避免样式出错,App.vue文件代码如下:

<template>
  <div id="app">
    <open-layers-map></open-layers-map>
  </div>
</template>

<script>
import OpenLayersMap from './views/OpenLayersMap.vue'
export default {
  components: { OpenLayersMap },
  name: 'App'
}
</script>

<style>
#app {
  /* font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px; */
}
</style>

在 src 文件夹下创建 view 文件夹,同时创建 OpenLayersMap.vue 文件,详细代码如下:

<template>
  <div>
    <div id='map' style='width: 100%; height: 920px'></div>
  </div>
</template>

<script>
import 'ol/ol.css'
import {Map, View, Feature} from 'ol'
import OSM from 'ol/source/OSM'
import VectorSource from 'ol/source/Vector'
import Cluster from 'ol/source/Cluster'
import {Vector as VectorLayer, Tile as TileLayer} from 'ol/layer'
import {Style, Fill as StyleFill, Stroke as StyleStroke, Circle as StyleCircle, Text as StyleText} from 'ol/style'
import { Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon } from 'ol/geom'
import { Draw as InteractionDraw } from 'ol/interaction'

export default {
  name: 'OpenLayersMap',
  data () {
    return {
      map: null,
      points: [],
      // 线条点数组
      linePoints: [],
      // 多边形数组
      polygonPoints: [],
    }
  },
  methods: {
    createMap () {
      let _this = this

      this.map = new Map({
        target: 'map',
        layers: [
          new TileLayer({
            source: new OSM({})
          }),
        ],
        view: new View({
          // 设置中心点,默认厦门,用于规划厦门市的未来发展
          center: [118.15075122802735, 24.482664909344276],
          projection: 'EPSG:4326',
          // 设置缩放倍数
          zoom: 13,
          minZoom: 6,
          maxZoom: 20
        })
      })
      // 绑定点击事件
      this.map.on('click', function (e) {
        let coor = e.coordinate
        // console.log(e.coordinate)
        // console.log('lon:' + coor[0] + ',lat:' + coor[1])
        _this.handleClick(coor)
      })
      // 绘制聚合点
      _this.addMarker()
    },
    // 设置统一控制点击事件,需要画图方式在此处切换
    handleClick(point) {
      // 绘制连线
      // this.drawLineString(point)
      // 绘制点
      // this.drawPoint(point)
      // 绘制圆形
      // this.drawCircle(point)
      // 绘制多边形
      // this.drawPolygon(point)
    },
    // 绘制点位
    drawPoint (center) {
      let vectorLayer = this.getLayer()

      let point = new GeomPoint(center)
      let feature = new Feature(point)
      vectorLayer.getSource().addFeature(feature)
      this.map.addLayer(vectorLayer)
    },
    // 绘制连线
    drawLineString(point) {
      this.linePoints.push(point)
      let featureLine = new Feature({
        geometry: new GeomLineString(this.linePoints),
      });
      let source = new VectorSource()
      source.addFeature(featureLine)
      let layer = new VectorLayer()
      layer.setSource(source)
      this.map.addLayer(layer)
    },
    // 绘制区域圆形
    drawCircle (center) {
      let vectorLayer = this.getLayer()

      // 设置半径
      let circle = new GeomCircle(center, 0.003)// 新建圆对象
      let feature = new Feature(circle)// 新建Feature对象 并将circle传入
      vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
      this.map.addLayer(vectorLayer) // 将图层添至地图对象
    },
    //画多边形
    drawPolygon(point){
      this.polygonPoints.push(point)
      let feature = new Feature({
        geometry: new GeomPolygon([this.polygonPoints]),
        attributes: null
      });
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      });
      feature.setStyle(lineStyle);
      let source = new VectorSource();
      source.addFeature(feature)
      let vectorLayer = new VectorLayer({
        source: source
      })
      this.map.addLayer(vectorLayer)
    },
    // 设置聚合点
    addMarker() {
      let source = new VectorSource();
      // 随机创建200个要素,后台点位取出后按此格式处理
      for (let i = 1; i <= 200; i++) {
        let coordinates = [118.10 + Math.random() * 0.05, 24.48 + Math.random() * 0.05];
        let feature = new Feature(new GeomPoint(coordinates));
        source.addFeature(feature);
      }

      // 聚合
      let clusterSource = new Cluster({
        source: source,
        distance: 50
      })

      let clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature, resolution) {
          let size = feature.get('features').length;
          let style = new Style({
            image: new StyleCircle({
              radius: 20,
              stroke: new StyleStroke({
                color: 'white'
              }),
              fill: new StyleFill({
                color: '#AAD3DF'
              })
            }),
            text: new StyleText({
              text: size.toString(),
              fill: new StyleFill({
                color: 'black'
              })
            })
          })
          return style;
        }
      });

      this.map.addLayer(clusters)
    },
    // 获取新的 layer 图层对象
    getLayer () {
      return new VectorLayer({
        source: new VectorSource({
          features: ''
        }),
        // 设置样式,但不完全兼容
        // style: function (feature) {
        //   let style = new Style({
        //     stroke: new StyleStroke({
        //       color: '#E80000',
        //       width: 2
        //     }),
        //     fill: new StyleFill({
        //       color: 'rgba(0,0,0,0)'
        //     })
        //   })
        //   return style
        // }
      })
    }
  },
  mounted () {
    this.createMap()
  }

}
</script>

<style>

</style>

代码中已包含 Open Layers 组件的 点、线、面绘制以及聚合点展示,点、线、面绘制均由点击事件触发,可以在 handleClick 方法中打开或关闭。点聚合数据随机生成,在实际开发中由后端获取转成需要格式传入即可。handleClick 方法代码如下:

// 设置统一控制点击事件,需要画图方式在此处切换
handleClick(point) {
  // 绘制连线
  // this.drawLineString(point)
  // 绘制点
  // this.drawPoint(point)
  // 绘制圆形
  // this.drawCircle(point)
  // 绘制多边形
  // this.drawPolygon(point)
},

部分功能已添加样式处理,有特殊需求需要新建样式对象传入 feature。例如:

// 添加线的样式
let lineStyle = new Style({
  fill: new StyleFill({
    color: 'rgba(1, 210, 241, 0.1)'
  }),
  stroke: new StyleStroke({
    color: 'rgba(255, 0, 0)',
    width: 4,
  }),
});
feature.setStyle(lineStyle);

聚合点展示:

Logo

前往低代码交流专区

更多推荐