import { getAreaDataByAlgorithmKeysApi } from '@ztzf/apis' import * as Cesium from 'cesium' import * as turf from '@turf/turf' import L from 'leaflet' import 'leaflet/dist/leaflet.css' /** * 设置自定义识别区域--大屏 * @returns {{}} */ export const useIdentificationArea = () => { let viewerObj async function setArea(ai_types,viewer) { if (!ai_types.length)return viewerObj = viewer removeArea() const res = await getAreaDataByAlgorithmKeysApi(ai_types) const list = res.data.data list .filter(item => item.geo_data) .forEach(item => { const parsed = JSON.parse(item.geo_data) // 转为数组 const grouped = parsed.flat() // 再展开 // 计算多边形质心 let polygon = turf.polygon([parsed]); let center = turf.centerOfMass(polygon); const color = '#00ff06' viewerObj.entities?.add({ customType: 'identificationArea', customInfo: { ...item, }, position: Cesium.Cartesian3.fromDegrees(center.geometry.coordinates[0], center.geometry.coordinates[1], 0), label: { text: item.name, font: 'bold 12px Source Han Sans CN', fillColor: Cesium.Color.WHITE, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, disableDepthTestDistance: Number.POSITIVE_INFINITY, scale: 1.0, }, polygon: { hierarchy: Cesium.Cartesian3.fromDegreesArray(grouped), material: Cesium.Color.fromCssColorString(color).withAlpha(0.5), classificationType: Cesium.ClassificationType.TERRAIN, }, polyline: { positions: Cesium.Cartesian3.fromDegreesArray([...grouped, grouped[0], grouped[1]]), clampToGround: true, width: 1.5, material: Cesium.Color.fromCssColorString(color), }, }) }) } function removeArea() { const thisList = viewerObj?.entities?.values?.filter(item => item?.customType === 'identificationArea') thisList?.forEach(item => { viewerObj.entities.remove(item) }) } onBeforeUnmount(()=>{ removeArea() }) return { setArea, removeArea } } /** * 设置自定义识别区域--h5 * @returns {{}} */ export const useIdentificationAreaForApp = () => { // 初始化图层 let mapLayerSource = null async function setArea(ai_types,viewer) { if (!ai_types.length) return // 清空所有图层 if (mapLayerSource) { mapLayerSource.clearLayers(); } mapLayerSource = viewer const res = await getAreaDataByAlgorithmKeysApi(ai_types) const list = res.data.data list .filter(item => item.geo_data) .forEach(item => { const parsed = JSON.parse(item.geo_data); // 转为数组 const grouped = parsed.flat(); // 再展开 // 3. 计算多边形质心 const turfPolygon = turf.polygon([parsed]); const center = turf.centerOfMass(turfPolygon); const centerLatLng = [center.geometry.coordinates[1], center.geometry.coordinates[0]]; const labelMarker = L.marker(centerLatLng, { icon: L.divIcon({ className: 'polygon-label', html: `
${item.name || '未命名'}
`, iconSize: null, // 让div决定大小 iconAnchor: null // 不需要锚点,用CSS transform居中 }), interactive: false, // 标签不参与交互 // zIndexOffset: 1000 // 确保标签在最上层 }); // 将坐标数组转换为 Leaflet 格式 [lat, lng, lat, lng...] -> [[lat, lng], [lat, lng]...] const latLngs = []; for (let i = 0; i < grouped.length; i += 2) { latLngs.push([grouped[i + 1], grouped[i]]); // 注意:Leaflet 是 [lat, lng] 顺序 } // 创建多边形(填充区域) const polygon = L.polygon(latLngs, { color: '#00ff06', fillColor: '#00ff06', fillOpacity: 0.5, weight: 0, // 隐藏多边形边框,使用折线作为边框 }); // 创建折线(边框) const polyline = L.polyline([...latLngs, latLngs[0]], { // 闭合多边形 color: '#00ff06', weight: 1.5, opacity: 1, fill: false }); // 将两个图层组合在一起 const group = L.featureGroup([polygon, polyline, labelMarker]); // 添加到图层组 mapLayerSource.addLayer(group); }); } function removeArea() { if (mapLayerSource) { mapLayerSource.clearLayers(); } } onBeforeUnmount(()=>{ mapLayerSource.clearLayers(); }) return { setArea, removeArea } }