高德Loca地图可视化加载Geojson实现地图楼块可视化

4,343 阅读2分钟

前言

最近在做一个关于某医院能耗的项目,可视化方面需要在地图上展示出医院楼块,并添为各个楼块添加交互事件,实现医院各个楼块乃至楼层的能耗检测。

技术

地图使用高德地图api,前端框架为Vue.js,前端ui组件库使用elementUi,使用npm包管理工具

搭建项目

在一个空文件夹下

vue create name

优化项目目录结构

加载高德地图

在vue中加载高德我们可以直接在public下的index.html中通过script脚本在线导入,这里我们直接用JSAPI Loader

  1. 在vue项目中下安装Loader:
npm i @amap/amap-jsapi-loader --save
  1. 项目中新建一个main.vue文件,作为承载地图的组件:
<template>
    <div id="container"></div> 
</template>

此时一定要为容器div设置宽高,不然地图无法显示

  1. 我们再新建一个initMap.js文件,将 AMapLoader 导入并将初始化地图initMap方法导出:

Loader的加载方法参考vue中加载高德地图


import AMapLoader from '@amap/amap-jsapi-loader'
const initMap = function () {
  window._AMapSecurityConfig = {
    securityJsCode: '你的安全密钥'
  }
  return AMapLoader.load({
    'key': '你的key', // 申请好的Web端开发者Key,首次调用 load 时必填
    'version': '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    'plugins': [],
    'AMapUI': { // 是否加载 AMapUI
      'version': '1.1', // AMapUI 缺省 1.1
      'plugins': ['overlay/SimpleMarker', 'overlay/SvgMarker'] // 需要加载的 AMapUI ui插件
    },
    'Loca': { // 是否加载 Loca, 缺省不加载
      'version': '2.0.0' // Loca 版本,缺省 1.3.2
    }
  })
}

export default initMap

  1. 再刚刚创建的main.vue文件中导入initMap方法

<template>
    <div id="map" class="map">

    </div>
</template>

<script>
var map //初始化一个map变量存储map对象
import initMap from '@/utils/map/initMap.js'
export default {
  name: '',
  components: {},
  data () {
    return {}
  },
  methods: {
  initMap().then((AMap)=>{
        map = new AMap.Map('map', {
          zIndex: 15,
          zoom: 18,
          pitch: 50,
          rotation: -6,
          showIndoorMap: false,
          showLabel: false,
          center: [114.502009, 36.618939],
          features: ['bg', 'point', 'road'],
          viewMode: '3D',
        })
  })
  }
}
</script>

地图加载成功:

高德地图支持自定义主题,根据需求自定义合适的地图样式 自定义地图样式

image.png

加载geojson

1. 获取楼块的geojson

通过geojson生成工具生成所需要的楼块点位,这里我推荐一些好用的geojson工具网站: geojson在线编辑 json在线编辑bejson

将获取到的json直接复制到项目的一个.json文件中,或者放入数据库通过接口获取。

2. 高德Loca数据可视化

用高德Loca数据可视化加载geojson 将准备好的楼块geojson通过import导入到main.vue文件中, 使用Loca的PolygonLayer图层加载楼块。具体教程参考:高德Loca数据可视化参考手册

<script>
var map //初始化一个map变量存储map对象
import hospitalJson from '@/static/hospital.json' // 事先准备好的geojson
import initMap from '@/utils/map/initMap.js'
export default {
  name: '',
  components: {},
  data () {
    return {}
  },
  methods: {
  initMap().then((AMap)=>{
        map = new AMap.Map('map', {
          zIndex: 15,
          zoom: 18,
          pitch: 50,
          rotation: -6,
          showIndoorMap: false,
          showLabel: false,
          center: [114.502009, 36.618939],
          features: ['bg', 'point', 'road'],
          viewMode: '3D',
        })
        this.locaInit(map, Loca)
  })
  }
  locaInit (map, Loca) {
      // 设置绘制loca的map对象
      var loca = new Loca.Container({
        map
      }) 
      
      // 用GeoJSONSource方法处理准备好的geojson
      var geo = new Loca.GeoJSONSource({
        data: hospitalJson
      })
      
      // 设置光源效果
      loca.ambLight = {
        intensity: 0.55,
        color: '#fff'
      }
      loca.dirLight = {
        intensity: 1,
        color: '#5BD6EA',
        target: [0, 0, 0],
        position: [0, -1, 1]
      }
      loca.pointLight = {
        color: '#EFFFFF',
        position: [112.028276, 31.58538, 2000000],
        intensity: 0.2,
        distance: 5000000
      }
      var pl = new Loca.PolygonLayer({
        map: map,
        zIndex: 11,
        hasSide: true
      })
      pl.setSource(geo)
      // 根据需求设置楼块样式
      pl.setStyle({
        unit: 'meter',
        texture: 'https://a.amap.com/Loca/static/loca-v2/demos/images/windows.jpg',
        textureSize: [350, 200],
        height: (index, f) => {
          const name = f.properties.name
          const condition1 = name === '公路' || name === '不重要建筑'
          const condition2 = hospitals.indexOf(name) > -1
          if (condition1 || condition2) {return 0} else {return f.properties.floor * 1.5 + 15}
        },
        topColor: (index, f) => {
          const name = f.properties.name
          return hospitals.indexOf(name) > -1 ? 'rgba(255,255,255,0)' : name.indexOf('公路') > -1 ? '#1C70AF' : '#282B3B'
        },
        sideTopColor: (index, f) => {
          const name = f.properties.name
          return hospitals.indexOf(name) > -1 ? '#fff00' : name.indexOf('公路') > -1 ? '#E2FFFF' : '#06477F'
        },
        sideBottomColor: (index, f) => {
          const name = f.properties.name
          return hospitals.indexOf(name) > -1 ? '#fff00' : name.indexOf('公路') > -1 ? '#E2FFFF' : '#032653'
        }
      })
    },
}
</script>

最后看一下楼块展示效果吧:

image.png

结尾

目前仅仅加载出来了楼快的样式,楼快如何添加事件以及楼块添加展示楼号楼名称标记还正在研究中,解决以上问题后续我会继续更新。