保姆级教程:在ThingsBoard中集成高德地图Widget(附完整SQL与TypeScript源码)
·
深度集成高德地图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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更多推荐

所有评论(0)