/** * 高德地图点标记绘制相关 */ import { map, AMap } from './index' import { useToolboxStore } from '@/stores/toolbox' import util from './util' import * as echarts from 'echarts' const toolboxStore = useToolboxStore() var _massMarks = undefined // 环信码等级和对应颜色 const ringCodeLevelColors = [ '#52c41a', // 绿色 '#faad14', // 黄色 '#f5222d', // 红色 ] /** * 绘制海量点标记 * @param {Array} shops 店铺对象数组 * @param {Object} shops[].shop 店铺基本信息 * @param {string} shops[].shop.name 店铺名称 * @param {string} shops[].shop.address 店铺地址 * @param {number} shops[].shop.latitude 纬度 * @param {number} shops[].shop.longitude 经度 * @param {string} shops[].shop.ringCodeLevel 最新环信码等级 * @param {string} shops[].shop.ringCodePublishTime 最新环信码发布时间 * @param {Array} shops[].recentData 近1小时的监测数据 * @param {string} shops[].recentData[].sampleTime 数据采样时间 * @param {number} shops[].recentData[].oilSmokeConcentration 油烟浓度 * @param {number} shops[].recentData[].purifierCurrent 净化器电流 * @param {number} shops[].recentData[].fanCurrent 风机电流 */ function drawMassMarks(shops) { // 配置样式 const massMarksStyle = ringCodeLevelColors.map((color, index) => ({ url: createCustomMarker(color), size: new AMap.Size(20, 20), anchor: new AMap.Pixel(10, 10), })) // 准备海量点数据 const massMarksData = shops.map((shop, index) => { // 根据环信码等级获取颜色 const color = getColorByRingCodeLevel(shop.shop.ringCodeLevel) return { id: index, name: shop.shop.name, lnglat: [shop.shop.longitude, shop.shop.latitude], style: shop.shop.ringCodeLevel, // 样式索引,对应 massMarksStyle extData: shop, // 存储完整的店铺信息 } }) // 清除现有的海量点标记 if (window.massMarks) { window.massMarks.clear() } // 创建新的海量点标记 window.massMarks = new AMap.MassMarks(massMarksData, { zIndex: 111, cursor: 'pointer', style: massMarksStyle, }) // 添加点击事件 window.massMarks.on('click', function (e) { const shop = e.data.extData showShopInfoWindow(shop) }) var marker = new AMap.Marker({ content: ' ', map: map, offset: new AMap.Pixel(13, 12), }) var timeout window.massMarks.on('mouseover', (e) => { if (timeout) { clearTimeout(timeout) } marker.setPosition(e.data.lnglat) marker.setLabel({ content: e.data.name }) map.add(marker) timeout = setTimeout(() => { map.remove(marker) }, 2000) }) // 添加到地图 window.massMarks.setMap(map) util.setBound(massMarksData.map((item) => item.lnglat)) } /** * 根据环信码等级获取颜色 * @param {string} level 环信码等级 * @returns {string} 颜色值 */ function getColorByRingCodeLevel(level) { switch (level + '') { case '0': return '#52c41a' // 绿色 case '1': return '#faad14' // 黄色 case '2': return '#f5222d' // 红色 default: return '#8c8c8c' // 灰色 } } /** * 根据环信码等级获取中文 * @param {string} level 环信码等级 * @returns {string} 中文表示 */ function getRingCodeLevelText(level) { switch (level + '') { case '0': return '绿色' case '1': return '黄色' case '2': return '红色' default: return '未知' } } /** * 创建自定义标记 * @param {string} color 标记颜色 * @returns {string} 标记的SVG URL */ function createCustomMarker(color) { const svg = ` ` return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg))) } /** * 显示店铺信息窗口 * @param {Object} shop 店铺对象 */ function showShopInfoWindow(shop) { // 准备信息窗口内容 // const content = ` //
//

${shop.shop.name}

//
//

地址:${shop.shop.address}

//

环信码等级:${shop.shop.ringCodeLevel}

//

环信码发布时间:${shop.shop.ringCodePublishTime}

//

近1小时监测数据

//
// ${shop.recentData // .map( // (item) => ` //
//

采样时间:${item.sampleTime}

//

油烟浓度:${item.oilSmokeConcentration} mg/m³

//

净化器电流:${item.purifierCurrent} A

//

风机电流:${item.fanCurrent} A

//
// `, // ) // .join('')} //
//
//
// ` const content = `

${shop.shop.name}

地址:${shop.shop.address}

环信码等级:${getRingCodeLevelText(shop.shop.ringCodeLevel)}

环信码发布时间:${shop.shop.ringCodePublishTime}

近1小时监测数据

` // 清除现有的信息窗口 if (window.infoWindow) { window.infoWindow.close() } // 创建新的信息窗口 window.infoWindow = new AMap.InfoWindow({ content: content, size: new AMap.Size(400, 400), offset: new AMap.Pixel(-24, -80), }) // 打开信息窗口 window.infoWindow.open(map, [shop.shop.longitude, shop.shop.latitude]) // 等待信息窗口加载完成后初始化图表 setTimeout(() => { const chartdom = document.getElementById('infowindowChartContainer') if (chartdom) { initChart(chartdom, shop.recentData) } }, 100) } /** * 初始化监测数据图表 * @param {Array} data 监测数据 */ function initChart(chartdom, data) { // 准备图表数据 const times = data.map((item) => item.sampleTime) const oilSmokeData = data.map((item) => item.oilSmokeConcentration) const purifierData = data.map((item) => item.purifierCurrent) const fanData = data.map((item) => item.fanCurrent) // 初始化图表 const chart = echarts.init(chartdom) // 图表配置 const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985', }, }, }, legend: { data: ['油烟浓度', '净化器电流', '风机电流'], top: 0, }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true, }, xAxis: [ { type: 'category', boundaryGap: false, data: times.map((time) => time.split(' ')[1]), axisLabel: { rotate: 0, fontSize: 10, }, }, ], yAxis: [ { type: 'value', name: '油烟浓度 (mg/m³)', position: 'left', left: '30%', }, { type: 'value', name: '电流 (A)', position: 'right', }, ], series: [ { name: '油烟浓度', type: 'line', data: oilSmokeData, yAxisIndex: 0, smooth: true, }, { name: '净化器电流', type: 'line', data: purifierData, yAxisIndex: 1, smooth: true, }, { name: '风机电流', type: 'line', data: fanData, yAxisIndex: 1, smooth: true, }, ], } // 应用配置 chart.setOption(option) // 响应式处理 window.addEventListener('resize', function () { chart.resize() }) } /** * 清除海量点标记 */ function clearMassMarks() { if (window.massMarks) { window.massMarks.clear() window.massMarks.setMap(null) window.massMarks = null } if (window.infoWindow) { window.infoWindow.close() window.infoWindow = null } } export default { drawMassMarks, clearMassMarks, // /** // * 绘制海量点标记 // * @param fDatas 完整监测数据 // * @param _factor 当前展示的监测因子对象 // */ // drawMassMarks(fDatas, _factor, onClick) { // if (!toolboxStore.dataMarkerStatus) { // return; // } // this.clearMassMarks(); // const lnglats = fDatas.lnglats_GD; // var data = []; // for (let i = 0; i < lnglats.length; i++) { // data.push({ // lnglat: lnglats[i], //点标记位置 // name: `${fDatas.times[i]}
${_factor.factorName}: ${_factor.datas[i].factorData} μg/m³`, // id: i // }); // } // // 创建样式对象 // var styleObject = { // url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png', // // url: './asset/mipmap/ic_up_white.png', // 图标地址 // size: new AMap.Size(11, 11), // 图标大小 // anchor: new AMap.Pixel(5, 5) // 图标显示位置偏移量,基准点为图标左上角 // }; // var massMarks = new AMap.MassMarks(data, { // zIndex: 5, // 海量点图层叠加的顺序 // zooms: [15, 18], // 在指定地图缩放级别范围内展示海量点图层 // style: styleObject // 设置样式对象 // }); // massMarks.on('click', (event) => { // const i = event.data.id; // // 3. 自定义点击事件 // onClick(i); // }); // var marker = new AMap.Marker({ // content: ' ', // map: map, // offset: new AMap.Pixel(13, 12) // }); // var timeout; // massMarks.on('mouseover', (e) => { // if (timeout) { // clearTimeout(timeout); // } // marker.setPosition(e.data.lnglat); // marker.setLabel({ content: e.data.name }); // map.add(marker); // timeout = setTimeout(() => { // map.remove(marker); // }, 2000); // }); // _massMarks = massMarks; // map.add(massMarks); // }, // clearMassMarks() { // if (_massMarks) { // map.remove(_massMarks) // _massMarks = undefined // } // }, /** * 创建标记点 * @param {string | Array} img 图标或图标数组 * @param {Array} dataList 监测数据 * @param {boolean} collision 标注避让 * @returns */ createLabelMarks(img, dataList, collision = true, showTxt = true) { const layer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, // 开启标注避让,默认为开启,v1.4.15 新增属性 collision: collision, // 开启标注淡入动画,默认为开启,v1.4.15 新增属性 animation: true, }) map.add(layer) // var markers = []; for (var i = 0; i < dataList.length; i++) { const data = dataList[i] var curData = { name: data.name, position: [data.longitude, data.latitude], zooms: [10, 20], opacity: 1, zIndex: 10, icon: { type: 'image', image: typeof img === 'string' ? img : img[i], // clipOrigin: [14, 92], // clipSize: [50, 68], size: [30, 30], anchor: 'bottom-center', angel: 0, retina: true, }, text: { content: showTxt ? data.name : '', direction: 'top', offset: [0, -5], style: { fontSize: 16, fontWeight: 'normal', fillColor: '#fff', strokeColor: '#333', strokeWidth: 0, backgroundColor: '#122b54a9', }, }, } curData.extData = { index: i, } var labelMarker = new AMap.LabelMarker(curData) // markers.push(labelMarker); layer.add(labelMarker) } return layer }, createMarker({ position, img, title, content, label = '', extData }) { //创建 AMap.Icon 实例: const icon = new AMap.Icon({ size: new AMap.Size(30, 30), //图标尺寸 image: img, //Icon 的图像 // imageOffset: new AMap.Pixel(-9, -3), //图像相对展示区域的偏移量,适于雪碧图等 imageSize: new AMap.Size(30, 30), //根据所设置的大小拉伸或压缩图片 }) const marker = new AMap.Marker({ position: position, // offset: new AMap.Pixel(-13, -30), icon: icon, //添加 icon 图标 URL content: content, title: title, label: { content: label, direction: 'bottom', }, extData, }) // map.add(marker); return marker }, }