ArcGis for javascript 地图组件封装,超级简单!!!

效果图

在这里插入图片描述
在线预览 如果跟上图不一致请按 Ctrl + F5,或在评论区反馈。

前言

看过本专栏前3篇童鞋的应该知道,将所有功能整合在一起代码量是很大的,并且可能地图上需要绘制很多线和点,项目中可能有几十处需要应用到 ArcGis地图。本篇是将另外3篇实现的功能结合在一起封装成 Vue组件,力求使用极简的 Api 实现 绘制线条、绘制自定义图标、获取Graphic的数据、底图切换、添加小部件 等功能,使代码得到充分的复用。

ArcGisMap组件

<template>
  <div id="map" class="map-container"></div>
</template>

<script>
import {
     
      loadModules } from 'esri-loader'
import {
     
      manyGraphics } from '@/utils/arcgisUtils'

export default {
     
     
  name: 'ArcGisMap',
  props: {
     
     
    // 选择加载地图自定义部件 ['switch-map', 'full-screen']
    tools: {
     
     
      type: Array,
      default: () => []
    },
    // 图形数据
    graphicsData: {
     
     
      type: Array,
      default: () => []
    },
    // 地图初始中心点
    centerPoint: {
     
     
      type: Array,
      default: () => [0, 0]
    },
    // 初始底图
    defaultBaseMap: {
     
     
      type: String,
      default: 'osm'
    },
    // 初始缩放级别
    zoom: {
     
     
      type: Number,
      default: 12
    }
  },
  data () {
     
     
    return {
     
     
      view: null,
      // 用于切换底图ID的数组
      baseMaps: ['osm', 'satellite', 'terrain']
    }
  },
  mounted () {
     
     
    const {
     
      defaultBaseMap, centerPoint, zoom, graphicsData } = this
    loadModules(
      ['esri/Map', 'esri/views/MapView', 'esri/Graphic'],
      {
     
      css: true }
    )
      .then(
        ([ArcGISMap, MapView, Graphic]) => {
     
     
          const map = new ArcGISMap({
     
     
            basemap: defaultBaseMap
          })

          this.view = new MapView({
     
     
            container: document.getElementById('map'),
            map: map,
            center: centerPoint,
            zoom: zoom
          })

          // 将图形添加到视图的图形层
          graphicsData.length && this.view.graphics.addMany(manyGraphics(Graphic, graphicsData))

          // 绑定点击事件
          this.view.on('click', e => {
     
     
            this.view.hitTest(e)
              .then(res => {
     
     
                // 获取每个图形上的ID
                res.results.length && this.$emit('clickGraphic', res.results[0].graphic.attributes)
              })
          })

          // 添加自定义控件
          this.tools.includes('switch-map') && this.view.ui.add(this.switchMapBtn(map), 'top-left')
          this.tools.includes('full-screen') && this.view.ui.add(this.fullScreenBtn(), 'top-left')
        }
      )
  },
  methods: {
     
     
    // 地图切换按钮
    switchMapBtn (map) {
     
     
      const btn = document.createElement('img')
      btn.src = require('./icons/switch-map.jpg')
      btn.style.width = '32px'
      btn.style.height = '32px'
      btn.style.cursor = 'pointer'
      btn.onclick = () => {
     
     
        let index = this.baseMaps.indexOf(map.basemap.id)
        map.basemap = index < this.baseMaps.length - 1 ? this.baseMaps[++index] : this.baseMaps[0]
      }
      return btn
    },
    // 地图全屏按钮
    fullScreenBtn () {
     
     
      const btn = document.createElement('div')
      btn.id = 'full-screen-btn'
      btn.style.width = '32px'
      btn.style.height = '32px'
      btn.style.cursor = 'pointer'
      btn.onclick = function () {
     
     
        const mapContainer = document.getElementById('map')
        const _body = document.body
        this.classList.toggle('full-screen')
        mapContainer.classList.toggle('full-screen')
        mapContainer.classList.contains('full-screen') ? (_body.style.overflow = 'hidden') : (_body.style.overflow = '')
      }
      return btn
    }
  },
  beforeDestroy () {
     
     
    this.view && (this.view.container = null)
  }
}
</script>

<style scoped lang="less">
.map-container {
     
     
  width: 100%;
  height: 100%;
  background: #f5f5f5;

  &.full-screen {
     
     
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1;
  }

  /deep/ #full-screen-btn {
     
     
    background: #fff url('./icons/full-screen.svg') no-repeat center center / 100% 100%;

    &.full-screen {
     
     
      background-image: url('./icons/normal-screen.svg');
    }
  }
}

</style>

arcgisUtils.js

/**
 * 创建线
 * @param Graphic 实例对象
 * @param paths 路径经纬度数组
 * @param color 路径的颜色
 * @param borderWidth 路径的宽度
 * @param id  该图形的 ID,用于判断点击的图形
 * @returns {*}
 */
export function createLineGraphic (Graphic, paths, color, borderWidth, id) {
    
    
  return new Graphic({
    
    
    geometry: {
    
    
      type: 'polyline',
      paths: paths
    },
    symbol: {
    
    
      type: 'simple-line',
      color: color, // 颜色 rgb or rgba [255, 0, 0, 0.5] or 16进制
      width: borderWidth
    },
    attributes: {
    
    
      id: id
    }
  })
}

/**
 * 创建点
 * @param Graphic
 * @param lng 点的位置
 * @param lat
 * @param markerUrl 图片的 url
 * @param width 点的大小
 * @param height
 * @param id
 * @returns {*}
 */
export function createPointGraphic (Graphic, lng, lat, markerUrl, width, height, id) {
    
    
  return new Graphic({
    
    
    geometry: {
    
    
      type: 'point',
      longitude: lng,
      latitude: lat
    },
    symbol: {
    
    
      type: 'picture-marker',
      url: markerUrl,
      width: width,
      height: height
    },
    attributes: {
    
    
      id: id
    }
  })
}

/**
 * 生成 'Graphic实例' 数组
 * @param Graphic Graphic类
 * @param graphicsData 生成 Graphic 实例的数据
 * @returns {[]}
 */
export function manyGraphics (Graphic, graphicsData) {
    
    
  const graphics = []
  graphicsData.forEach(item => {
    
    
    if (item.paths) {
    
    
      graphics.push(createLineGraphic(Graphic, ...Object.values(item)))
    } else if (item.lng) {
    
    
      graphics.push(createPointGraphic(Graphic, ...Object.values(item)))
    }
  })
  return graphics
}

父组件

<template>
  <div class="arcgis-map-wrapper">
    <arc-gis-map
      :tools="['switch-map', 'full-screen']"
      :graphicsData="graphicsData"
      :centerPoint="[117.17144639449873, 31.83296921125205]"
      @clickGraphic="getParams"
    />
  </div>
</template>

<script>
import ArcGisMap from '@/components/ArcgisMap/ArcgisMap'

export default {
     
     
  components: {
     
      ArcGisMap },
  data () {
     
     
    return {
     
     
      // 图形数据
      graphicsData: [
        {
     
     
          paths: [
            [117.129359, 31.839979],
            [117.128810, 31.839979],
            [117.128810, 31.832240],
            [117.227610, 31.833600]
          ],
          color: '#1e80ff',
          width: 5,
          id: 'Hello world'
        },
        {
     
     
          lng: 117.129359,
          lat: 31.839979,
          markerUrl: require('@/assets/img/view-start.png'),
          width: '32px',
          height: '48px',
          id: 'Foo'
        },
        {
     
     
          lng: 117.227610,
          lat: 31.833600,
          markerUrl: require('@/assets/img/view-end.png'),
          width: '32px',
          height: '48px',
          id: 'Bar'
        }
      ]
    }
  },
  methods: {
     
     
    getParams (e) {
     
     
      this.$message.info(JSON.stringify(e))
    }
  }
}
</script>

<style lang="less" scoped>
.arcgis-map-wrapper {
     
     
  width: 100%;
  height: 100%;
}
</style>

结束语

呼~~又贴了这么多又臭又长的代码,其实我看博文第一看有没有demo图片,第二看是不是高亮代码,不然很难深入看下去,贴这么多代码是为了需要的人能第一时间看到想要的东西。
为什么开 ArcGisJS系列 专栏?主要是入坑完 ArcGisJS 后,感觉要记录一下,万一以后的项目又用到 ArcGisJS 怎么办,这东西半年不用就忘。虽然本专栏内文章都是基于 ArcGisJS 的粗浅使用,但是忘了七七八八后再折腾一下也得花不少时间。而记录下来,不仅加深了理解,也能帮助初次接触的人少走更多弯路。

猜你喜欢

转载自blog.csdn.net/dizuncainiao/article/details/108479865