showDevicesOnMap(devices) {
// 清除旧图层(确保移除所有相关图层)
const layersToRemove = [
"debug-layer",
"devices-layer",
"device-labels",
"label-backgrounds",
"selection-layer",
];
layersToRemove.forEach((layerId) => {
if (this.mapObj.getLayer(layerId)) this.mapObj.removeLayer(layerId);
});
if (this.mapObj.getSource("devices-source")) {
this.mapObj.removeSource("devices-source");
}
// 创建GeoJSON数据源(确保每个特征有唯一ID)
const geojson = {
type: "FeatureCollection",
features: devices.map((device, index) => ({
type: "Feature",
id: device.id, // 确保id唯一
geometry: {
type: "Point",
coordinates: [device.longitude, device.latitude],
},
properties: {
...device,
index: index + 1,
isSelected: this.selectedDeviceId === device.id,
},
})),
};
// 添加数据源
this.mapObj.addSource("devices-source", {
type: "geojson",
data: geojson,
generateId: true, // 如果特征本身没有id,则生成一个
});
// 预加载图标
const loadPromises = [
this.loadImageSafe("jk_online", "/images/jk_online.png"),
this.loadImageSafe("jk_unline", "/images/jk_unline.png"),
];
// 加载图标并添加图层
Promise.all(loadPromises)
.then(() => {
// 检查图标路径是否正确(使用绝对路径)
const iconBaseUrl = window.location.origin + "/images/";
console.log("图标访问路径:", iconBaseUrl + "jk_online.png");
// 在设备图层前添加调试层
if (!this.mapObj.getLayer("debug-layer")) {
this.mapObj.addLayer({
id: "debug-layer",
type: "circle",
source: "devices-source",
paint: {
"circle-radius": 5,
"circle-color": "#FF0000",
"circle-opacity": 0.8
}
});
console.log("调试层已添加");
}
// 添加设备图标层
if (!this.mapObj.getLayer("devices-layer")) {
this.mapObj.addLayer({
id: "devices-layer",
type: "symbol",
source: "devices-source",
layout: {
"icon-image": "jk_online", // 固定使用在线图标,测试是否显示
"icon-size": 0.8,
"icon-anchor": "bottom",
"icon-allow-overlap": true,
},
});
}
// // 添加设备图标层
// if (!this.mapObj.getLayer("devices-layer")) {
// this.mapObj.addLayer({
// id: "devices-layer",
// type: "symbol",
// source: "devices-source",
// layout: {
// "icon-image": [
// "case",
// ["==", ["get", "online"], true],
// "jk_online",
// "jk_unline",
// ],
// "icon-size": 0.8,
// "icon-anchor": "bottom",
// "icon-allow-overlap": true, // 防止图标被隐藏
// },
// });
// }
// 添加序号背景层(圆形)
if (!this.mapObj.getLayer("label-backgrounds")) {
this.mapObj.addLayer({
id: "label-backgrounds",
type: "circle",
source: "devices-source",
paint: {
"circle-radius": 10,
"circle-color": [
"case",
["==", ["feature-state", "isSelected"], true],
"#FF6666",
"#45CCDA",
],
"circle-stroke-width": 1,
"circle-stroke-color": "#fff",
"circle-translate": [0, -22], // 向上平移,与图标位置配合
},
});
}
// 添加序号文本层
if (!this.mapObj.getLayer("device-labels")) {
this.mapObj.addLayer({
id: "device-labels",
type: "symbol",
source: "devices-source",
layout: {
"text-field": ["get", "index"],
"text-font": ["Noto Sans Bold"],
"text-size": 12,
"text-offset": [0, -1.8], // 调整位置到背景圆中心
"text-anchor": "top",
"text-allow-overlap": true,
},
paint: {
"text-color": "#FFFFFF",
"text-halo-color": "rgba(0, 0, 0, 0.5)",
"text-halo-width": 1,
},
});
}
// 设置初始特征状态
devices.forEach((device) => {
this.mapObj.setFeatureState(
{ source: "devices-source", id: device.id },
{ isSelected: device.id === this.selectedDeviceId }
);
});
})
.catch((error) => {
console.error("图层添加失败:", error);
});
// 点击事件处理
this.mapObj.off("click"); // 移除旧的监听器,避免重复绑定
this.mapObj.on(
"click",
["devices-layer", "device-labels", "label-backgrounds"],
(e) => {
if (e.features && e.features.length > 0) {
const deviceId = e.features[0].properties.id;
this.toggleDeviceSelection(deviceId);
}
}
);
console.log('当前地图样式中的图片:', this.mapObj.getStyle());
console.log('设备源是否存在:', this.mapObj.getSource('devices-source'));
},
loadImageSafe(name, url) {
console.log(`Loading image: ${name} from ${url}`);
return new Promise((resolve) => {
if (this.mapObj.hasImage(name)) {
console.log(`Image ${name} already exists.`);
resolve();
} else {
this.mapObj.loadImage(url, (error, image) => {
if (error) {
console.error(`图片加载失败: ${url}`, error);
resolve(); // 即使失败也继续执行
} else {
this.mapObj.addImage(name, image);
resolve();
}
});
}
});
},打印结果Loading image: jk_online from /images/jk_online.png
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:678 Image jk_online already exists.
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:675 Loading image: jk_unline from /images/jk_unline.png
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:678 Image jk_unline already exists.
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:669 当前地图样式中的图片: {version: 8, sprite: 'minemap://sprite/sprite', glyphs: 'minemap://fonts/{fontstack}/{range}', sources: {…}, layers: Array(127)}
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:670 设备源是否存在: i {id: 'devices-source', _isLatLon: true, type: 'geojson', minzoom: 0, maxzoom: 18, …}图标访问路径: http://localhost:8080/images/jk_online.png
index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:570 调试层已添加地图上还是什么都没有