需申请key更换之后即可运行
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>多告警弹窗地图</title>
<style>
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.custom-alert-popup {
width: 220px;
background: #fff;
border-radius: 10px;
box-shadow: 0 0 10px rgba(255, 0, 0, 0.5);
padding: 10px;
position: relative;
font-size: 14px;
}
.alert-header {
font-weight: bold;
color: red;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
}
.close-btn {
background: none;
border: none;
cursor: pointer;
color: #888;
font-size: 16px;
}
.info-row {
margin: 4px 0;
}
.alarmimg {
width: 100%;
margin-top: 5px;
}
.room-info {
display: flex;
align-items: center;
justify-content: space-between;
}
.room-address {
font-weight: bold;
}
.user-icon {
font-size: 20px;
}
</style>
</head>
<body>
<div id="container"></div>
<audio id="myAudio" src="https://cdn.pixabay.com/download/audio/2022/08/12/audio_cb1eac5f89.mp3?filename=alarm-102078.mp3"></audio>
<script src="https://webapi.amap.com/maps?v=2.0&key=你自己的key"></script>
<script>
// 模拟老人数据
const elderList = [
{ id: 1, name: '张三', age: 80, avatar: 'https://i.pravatar.cc/50?img=1', position: [116.397428, 39.90923] },
{ id: 2, name: '李四', age: 75, avatar: 'https://i.pravatar.cc/50?img=2', position: [116.407428, 39.91923] },
{ id: 3, name: '王五', age: 85, avatar: 'https://i.pravatar.cc/50?img=3', position: [116.387428, 39.89923] }
];
const markerMap = new Map();
const activeOverlays = [];
const map = new AMap.Map("container", {
viewMode: '2D',
zoom: 15,
center: [116.397428, 39.90923]
});
const infoWindow = new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30) });
elderList.forEach(elder => {
const marker = new AMap.Marker({
position: elder.position,
offset: new AMap.Pixel(-25, -25),
content: `
<div style="
border-radius: 50%;
overflow: hidden;
width: 50px;
height: 50px;
border: 2px solid #fff;
box-shadow: 0 0 5px rgba(0,0,0,0.3);
">
<img src="${elder.avatar}" alt="${elder.name}" style="width: 100%; height: 100%; object-fit: cover;" />
</div>
`
});
marker.setMap(map);
markerMap.set(elder.id, marker);
marker.on('click', () => {
infoWindow.setContent(`<div><strong>${elder.name}</strong><br/>年龄:${elder.age}</div>`);
infoWindow.open(map, marker.getPosition());
});
});
if (elderList.length > 0) {
const lastElder = elderList[elderList.length - 1];
map.setZoomAndCenter(18, lastElder.position);
}
function onMQTTMessageReceived(message) {
if (Array.isArray(message)) {
message.forEach(msg => handleSingleMessage(msg));
} else {
handleSingleMessage(message);
}
}
function handleSingleMessage(msg) {
let position = msg.position;
const marker = markerMap.get(Number(msg.elderId));
if (!position && marker) {
position = marker.getPosition();
}
if (!marker || !position) {
console.warn(`未找到老人ID: ${msg.elderId}`);
return;
}
marker.setPosition(position);
map.setZoomAndCenter(18, position);
createCustomAlertPopup(msg, position);
}
function createCustomAlertPopup(msg, position) {
const popupDiv = document.createElement("div");
popupDiv.className = "custom-alert-popup";
popupDiv.innerHTML = `
<div class="alert-header">
紧急告警
<button class="close-btn">✖</button>
</div>
<div class="alert-content">
<div class="room-info">
<div><div class="room-address">${msg.alertaddress}</div></div>
<div class="user-icon">👤</div>
</div>
<div class="info-row"><span class="info-label">报警原因:</span><span style="color: red;">${msg.alertType}</span></div>
<div class="info-row"><span class="info-label">报警人员:</span><span>${msg.name}</span></div>
<div class="info-row"><span class="info-label">设备编号:</span><span>${msg.deviceImei}</span></div>
<div class="info-row"><span class="info-label">报警时间:</span><span>${msg.alertTime}</span></div>
<img class="alarmimg" src="https://i.gifer.com/7efs.gif" alt="报警图">
</div>
`;
const overlayMarker = new AMap.Marker({
position,
content: popupDiv,
offset: new AMap.Pixel(-110, -180),
zIndex: 9999
});
overlayMarker.setMap(map);
activeOverlays.push(overlayMarker);
popupDiv.querySelector(".close-btn").addEventListener("click", () => {
map.remove(overlayMarker);
const i = activeOverlays.indexOf(overlayMarker);
if (i !== -1) activeOverlays.splice(i, 1);
});
}
// 模拟报警触发(可替换为真实 MQTT 消息)
setTimeout(() => {
document.getElementById("myAudio").play();
onMQTTMessageReceived([
{
elderId: 2,
name: '李四',
deviceImei: '864176075607047',
alertType: '跌倒报警',
alertaddress: '金华小区三单元401',
alertTime: '2025-04-08 16:30:00'
},
{
elderId: 1,
name: '张三',
deviceImei: '1234567890',
alertType: '心率异常',
alertaddress: '幸福公寓2号楼402',
alertTime: '2025-04-08 16:32:00'
}
]);
}, 2000);
</script>
</body>
</html>