/**
* 高德地图点标记绘制相关
*/
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
},
}