深度集成高德地图Widget到ThingsBoard:从零构建自定义物联网可视化方案

1. 为什么选择高德地图替代默认地图组件?

在物联网仪表盘开发中,地图可视化是核心功能之一。ThingsBoard默认集成的OpenStreetMap和Google Maps虽然功能完善,但国内开发者常面临两个痛点:一是地图加载速度受网络环境影响,二是缺乏本土化地理数据支持。高德地图作为国内领先的数字地图服务,提供更精准的本地POI数据、更流畅的访问体验,以及符合国内用户习惯的中文标注。

关键技术对比

特性 OpenStreetMap Google Maps 高德地图
中文标注支持 有限 部分收费 完整支持
国内访问速度 较慢 不稳定 极快
坐标系 WGS84 WGS84 GCJ02(国内标准)
免费API调用额度 完全免费 有限制 企业级免费额度
离线支持 支持 不支持 支持SDK离线

开发环境准备

确保已部署ThingsBoard 3.3.1+版本,并准备好以下资源:

  • 高德地图开发者账号( 申请地址
  • Leaflet.js 1.7.1+(ThingsBoard内置依赖)
  • TypeScript编译环境

注意:高德地图API Key是集成必备条件,需在开发者平台创建Web端应用获取

2. 核心代码实现解析

2.1 创建高德地图Provider类

ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/ 目录下新建 amap.ts

import L from 'leaflet';
import LeafletMap from '../leaflet-map';
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models';

export class Amap extends LeafletMap {
  private map: L.Map;
  
  constructor(ctx: WidgetContext, $container: HTMLElement, 
              options: UnitedMapSettings) {
    super(ctx, $container, options);
    
    const tileUrl = 'https://wprd0{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8';
    
    this.map = L.map($container, {
      editable: !!options.editablePolygon,
      crs: L.CRS.EPSG3857 // 高德地图使用的坐标系
    }).setView(
      options?.defaultCenterPosition || [39.9042, 116.4074], // 默认北京中心
      options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL
    );

    L.tileLayer(tileUrl, {
      subdomains: ['1','2','3','4'],
      attribution: '©高德地图'
    }).addTo(this.map);

    super.initSettings(options);
    super.setMap(this.map);
  }

  // 重写坐标转换方法解决偏移问题
  latLngToPoint(latLng: L.LatLng): L.Point {
    return this.map.latLngToLayerPoint(latLng);
  }
}

2.2 注册地图Provider

修改 providers/index.ts 导出高德地图Provider:

import { Amap } from './amap';
import { aMapSettingsSchema } from '../schemes';

export const providerSets: { [key: string]: IProvider } = {
  // ...其他provider配置
  'a-map': {
    MapClass: Amap,
    schema: aMapSettingsSchema,
    name: 'a-map'
  }
};

2.3 配置Schema表单

schemes.ts 中定义高德地图特有的配置项:

export const aMapSettingsSchema = {
  schema: {
    title: '高德地图配置',
    type: 'object',
    properties: {
      tmApiKey: {
        title: '高德地图API Key',
        type: 'string',
        default: ''
      },
      tmDefaultMapType: {
        title: '默认地图类型',
        type: 'string',
        default: 'roadmap',
        enum: ['roadmap', 'satellite', 'hybrid']
      }
    },
    required: ['tmApiKey']
  },
  form: [
    'tmApiKey',
    {
      key: 'tmDefaultMapType',
      type: 'rc-select',
      multiple: false,
      items: [
        { value: 'roadmap', label: '街道图' },
        { value: 'satellite', label: '卫星图' },
        { value: 'hybrid', label: '混合图' }
      ]
    }
  ]
};

3. 数据库集成与Widget注册

3.1 执行SQL插入Widget配置

-- 最新数据地图Widget
INSERT INTO widget_type (id, created_time, alias, bundle_alias, descriptor, name, tenant_id) 
VALUES ('ac5009a1-87bc-11eb-9af3-33d602ee9fb3', 1618281154856, 'amap_maps', 'maps_v2', 
'{"type":"latest","sizeX":9,"sizeY":6,"resources":[],"templateHtml":"","templateCss":".error {\n color: red;\n}\n.tb-labels {\n color: #222;\n font: 12px/1.5 \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n text-align: center;\n width: 200px;\n white-space: nowrap;\n}","controllerScript":"self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2(''a-map'', false, self.ctx);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbMapWidgetV2.settingsSchema(''a-map'');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbMapWidgetV2.dataKeySettingsSchema(''a-map'');\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.24727730589425012,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"temperature\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.8437014651129422,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"type\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.7558240907832925,\"funcBody\":\"return \\\"colorpin\\\";\"}]},{\"type\":\"function\",\"name\":\"Second Point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.19266205227372524,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#9c27b0\",\"settings\":{},\"_hash\":0.7995830793603149,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"temperature\",\"color\":\"#8bc34a\",\"settings\":{},\"_hash\":0.04902495467943502,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"type\",\"color\":\"#3f51b5\",\"settings\":{},\"_hash\":0.44120841439482095,\"funcBody\":\"return \\\"thermomether\\\";\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"tmDefaultMapType\":\"roadmap\",\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"autocloseTooltip\":true,\"tooltipPattern\":\"<div style=''font-size: 13px;''><b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Temperature:</b> ${temperature} °C<br/><small>See advanced settings for details</small></div>\",\"markerImageSize\":34,\"tmApiKey\":\"84d6d83e0e51e481e50454ccbe8986b\",\"color\":\"#fe7569\",\"useColorFunction\":true,\"colorFunction\":\"var type = dsData[dsIndex][''type''];\\nif (type == ''colorpin'') {\\n\\tvar temperature = dsData[dsIndex][''temperature''];\\n\\tif (typeof temperature !== undefined) {\\n\\t var percent = (temperature + 60)/120 * 100;\\n\\t return tinycolor.mix(''blue'', ''red'', amount = percent).toHexString();\\n\\t}\\n\\treturn ''blue'';\\n}\\n\",\"useMarkerImageFunction\":true,\"markerImageFunction\":\"var type = dsData[dsIndex][''type''];\\nif (type == ''thermomether'') {\\n\\tvar res = {\\n\\t url: images[0],\\n\\t size: 40\\n\\t}\\n\\tvar temperature = dsData[dsIndex][''temperature''];\\n\\tif (typeof temperature !== undefined) {\\n\\t var percent = (temperature + 60)/120;\\n\\t var index = Math.min(3, Math.floor(4 * percent));\\n\\t res.url = images[index];\\n\\t}\\n\\treturn res;\\n}\",\"markerImages\":[\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAB/CAYAAAD4mHJdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACWAAAAlgB7MGOJQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAwgSURBVGiB7Zt5cBT3lce/v18fc89oRoPEIRBCHIUxp2ywCAgIxLExvoidZIFNxXE2VXHirIO3aqtSseM43qpNeZfYKecox3bhpJykYgdjDkU2mBAB5vCamMNYAgQyURBCoxnNPd39O/aP7hGSEUR24L/uqqf+zfR77/Pe69/Rv6kWwcgPLRIJfZUAa7xez2xd90QBwDSNZKlkHJHAK+l09mUA7BP4vPpRUVExMVoRef+L998njxx9X57vPi/PnTsnO850yPaT7XLXrrflqjtWymhF+HA0Gp0wEp/kHymEQqG4ptJDGzf+um5RUxMSiV7Z3Lyt88L5nozgHJWj4pGmpqZav99PWve04onHHuswmViQzWb7ruZX+Udgv8/z3A+f/NGye1evxssvb+wo5PMfTZs6bfqcuXNHL7hlweh58+ZVAOTUpk2b0p9dvjyqqmrs/b8ejpUMc+unzjgUCsXjsYruE+2n1JY/NedM0zCi0VjA7/d7/f4AAgE//H4/vF4fOjvP9h5695C/oaEhcN/q1SyTzVdnMpnklXzTq4EplUsXfmaRCgC7du3cOn78+KfGj59Add3z1Md1vV7vqPa2D1sA4MYbZ6qUiqVX9X21i4TQcfX19QCA6urquN/vn0kAPRQKpYbTnzRpUhgAampqAEFrPjVYSql7fD4AgK5r2tV0AcDj8WkAoOm6JJGeTw2+nocLdsEu2AW7YBfsgl2wC3bBLtgFu2AX7IJdsAt2wS7YBbtgF+yCXbALdsEu2AW7YBfsgl2wC76mh/ppjIQgXVloPxVSBRV0rBe455P6+kTKBYF3tonxY/IWarry7DvI298Tgp0PR9RzACaN1NeIS11U+EdvKXW3cMZvF8wCK10Sq2it2NAzakmukP/wmoP/KuId3BRUMg5uCfCSNVSKVn1rNto7Un8jLrUVqJ4Fi2eEQiEYBzOsy3SYL37TNQdzi8Q5FxkqJIQBsNLlYMGF/zqAJWBxSEogDAY+DJibYqTuRg4WFwO3OKhCYTExbKk5G/mbkSPP2DQhLA5IO/NhSz1MMP882BDgnAFQwdiVSs2vPVhYDIJLUMkBgw1favM6lJoZDDAYhKbAYsOX+rqAhcXAuQSIAKzhSy2vS8YmB7NYH4WCfM7kw5VaWtdpOO3bfWZJZVXgPxMX898bVsm6RhkTIseX29yyIErm/J5z5vwr6pvmsLYjBgeDwSpVJS/OmT1n1de+9qANZgLc4q9Dyj2qQhUhSSUAUCL7GBcchCymTEYBYNWqVXj30MGHT586PZEJ+WAul7ts8bjspd9QKDRNU2nz4z94YtI3H3oI+XwB//3j/9m77eRUUJ9/0eh4APGoDz6vCi4ksgUTmYyBC4k8RLGwtzF+EGu+tHqRqqrYtm0rXnzhhQ7G5cpsNnvyiuBIJFKnqvSd55772eilS5fhwIH9ye+/dPaEf1T9otW3T8GtiyYgGNBBymYEgLSbvakidu8/h01vnkYhcab1gcVs5tx5c6PHjh7DU0/9qFsINPb3939UZg28X11dXR0Qwtr9g8efqGtc+Bn89re/O7FhR9BXNaFm+n98uxHTZ1SDKQqKAihweZlITUVtXQwNs8fg+Bmzdk+bnmPdf/7bwsbGeO2ECaED+9/5XCxWuTGbzVpDwJpGNtx+28o77rr7bmzZsu3k7z+cMlHzeiPrvnoTwtVhFAVQHAZY4HBEoiAAeDXUjI/gyJGeQEd6TFj2tHYuXNgYy2azVe0fngiWDLNloHNFo4FZkXDsoTVr1+KD4x8U/3Ci1qP5PV7N74FeFUbClKDEriy57A5JANL5a68hnqoINL8OAPqbXbNp7clTxTVr1/oOHjr0MFXxq2Qy9wEFACnoY//6la9QAHj+9Q/eUL2RWkVXoWgqkhZBypRImkDKBFIWkLIk+h1JWdL+zrmeNCWSDFB0DYquQvWG637TcnozAKxbt45yTr8PAGowGBwVDAbvmT9/Pvbu3dddijV9WdUUUE0BUQm6kwaCYe+ljK/w8ruUdsYCBLlMEUQhoJoCygWM+LIvHTx4sGfevIbqYMD3BSFkJVUUrG5oaFABoPXwhd1UVUBVahtpKtoOnEV/gSHHgBwDso5c6XO6yNF24CNQTbV9qBRUUenuwz1/BoCZM2dplOJeSggWL1myFEII9IeXziIKBVUUW1QKo2Ci41Anei9kkWcY6Ex5R8qfc0wi0ZPF6QNnYeQNB2j7IQpFOtg0WwiBxoWNIBKLVQI6Z8rUqTh69FiWaFNmEIWgLFShoM5TZbIzgVxvFp6ID5rfA6JQgBAIxsGLJkrpAsycAcH4gN1gX0QPTW9vP5Grr58cJJTOpbqmjgWAnp6ei4QSEEJAKAGh1BbHCS2DLAFmMAimICwObnDnyYMsBtJL9oN89vRc7KWUQtOUsSqhSggA8sWivSEh9qBxTiCEAGRwQARUVaB67Hf5pZAQlA0Ayrq2LTAogVyhlLURNEw55yYABP2+4ED3vHSClBKQ9jiFdHqvEBCMQzAOKYSt6/ZqSGnbDPJRbgT93hAAcM4NyhjrBYDKylhswEEZJgYJFxDchnGTwSqasIomuMnsIDiH5GKIzUAQTsCVlZUxB9xLIUVbKpVEff3kiLTMfimEA7HP5bZgHMJ07mlJAiuaYEXT3jcZDMLkTgBD7exgBKRp9NfVTQwnk0kIKduoJGRH8/ZmhMNh4skc3DnEkDlAi4GbtqDDguVAmZM1M6yB68JyKsCGBqD373s7GAySnTt3gBDyFhWCvPHee/8HAJhTU5g0BMg4uMXBTT4AZSUTrGjBKpiwCnablQbDbZuyfTmAuRPMegA4euQIpCRbaCaTOd2XSLzX3d2Nu+64bR7PnP3LJSCDMBm4YW9FWcmyQYMytsW+Zpfdsm1MdinAdMc7K29bMedCdzeSyeS76XT6jLNI4PGf/+w5aLqOu25IjOOWKcSg0jJjcLZ2ecsZD5TdybqsOxC0ZYpbJ58frek6nn/+eVBJHgecjXkqk2nu7Ozcdfz4cdx556rJN5C3m8v3jBt2xpdnazjysawNy5lUbKkrbmtZsWL5pGNHj6Or62+7k5lMy5CFNdQKTfN6tAMvvvhSRe3EOqx/4oXXLvia7qO6CsVZrey5194KB5YpKSG5tHs+5/ZsZnEIk6Ei1fLH73373i/09fXi0fWPpgyTLchkMqeGgAEgHA5/vjJWsf2PmzYr1dXV+K8fP7vjLxduWkY8ilpetQZPg+UJxh63lzqlNDi7gTa3fuPraz6bzxXw79/5FutP51am0+kdZdaQ/2kzDKNDUci51179w8pbP3er8sAD6+pnVCWy+/fs21LAqBnlMT50qJXFLq2a2L/5gaVy7N133j69u7sb67/7iFHIFf4tlU6/Ppg1kLGU8hYAywBMeOWV13gfXb9+1Q+ffDL+4Ne/AcYY/tS8PbV5++4Dhy+MopY2ZrLiidQDgDBSp1TS+Y7psS65ZOHsW26++eYosxje2PwGNm586eKzz/x027+sXWsBOAfgbULIQQAgUspaAA8BGAfnsamrq4u0tZ0Q333kkdGmZS3f8JNnlBXLV0AOilRKCS7sWYlxjlKxgHw+j5Y3W/C/Tz/NQ6Hgjp9seKZ31py5ajwe4wAtz9zdAG5OpJTPAqgEgL5USkpu4eLFHloqFXniYh9t3bunauuWrStisSj5+/4vYnHTEkyZOhWqokBICcuy0N7ehr2trXjt1VeRzqTl3ffc81bjgsZELF4pQ6EAqa4eI6UEicfj5dhTKoCikynx6Bop5C14dJ2XcjmouipvvGFGoSJaWfr738/7tmzdjl/88pfIZjKwnH2SpmkIhSMYW1ODhvmNGFcztjhudFXR69Wgck58Hg+XEorH5ylDJYA8kVKOckpdB0ADIBOJhOzv70OhUFILuTzPZLNcSE6SfSlvJp0O5A1DN0qGDxLS4/OUAh6PGQqHC5XxeJEQgkgoRH1+L/wBP6LRuIjH4+Uf8gSAUwB+MbhzzQSwCMA0p/QUQADgNJ/PJ/v7+wnnnFiWkJZhKCYzKADoqiZUXeW67iGcSxKPx2QoFAo7AybnuE8COAZgHyHkxGXjeFAQEQCzANQCqAIQBeAH4AXgcex052w45TMcyQHIAOgBcBbAUUJI5uOM/wcaHmf3g9UM7QAAAABJRU5ErkJggg==\",\"data:image/png;base64,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

更多推荐