| | |
| | | |
| | | import DevicePopUpBox from '@/hooks/components/DevicePopUpBox.vue' |
| | | import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue' |
| | | |
| | | // 图标 |
| | | import offlineImg from '@/assets/images/home/useEventOperate/offline.png' |
| | | import onlineImg from '@/assets/images/home/useEventOperate/eventSingle.png' |
| | | import { render } from 'vue' |
| | | import { useStore } from 'vuex' |
| | | import { getCenterPoint } from '@/utils/cesium/mapUtil' |
| | |
| | | * 机巢聚合功能 |
| | | */ |
| | | |
| | | let arrColor = ["rgb(15,176,255)", "rgb(18,76,154)", "#40C4E4", "#42B2BE", "rgb(51,176,204)", "#8CB7E5", "rgb(0,244,188)", "#139FF0"] |
| | | let arrColor = [ |
| | | 'rgb(15,176,255)', |
| | | 'rgb(18,76,154)', |
| | | '#40C4E4', |
| | | '#42B2BE', |
| | | 'rgb(51,176,204)', |
| | | '#8CB7E5', |
| | | 'rgb(0,244,188)', |
| | | '#139FF0', |
| | | ] |
| | | |
| | | let index = 0 |
| | | function getColor () { |
| | | return arrColor[++index % arrColor.length] |
| | | function getColor() { |
| | | return arrColor[++index % arrColor.length] |
| | | } |
| | | |
| | | export const useMapAggregation = type => { |
| | | const { flyTo } = cesiumOperation() |
| | | export const useMapAggregation = (type, status) => { |
| | | const { flyTo } = cesiumOperation() |
| | | |
| | | const singleImg = type === 'device' ? uavImg : eventSingle |
| | | const mergeImg = type === 'device' ? aggregationImg : eventAggregationImg |
| | | const MapPopUpBox = type === 'device' ? DevicePopUpBox : EventPopUpBox |
| | | const styleTransform = type === 'device' ? 'translateY(-50%)' : 'translate(-50%,-110%)' |
| | | const singleImg = type === 'device' ? onlineImg : eventSingle |
| | | const offlinesingleImg = type === 'device' ? offlineImg : eventSingle |
| | | const mergeImg = type === 'device' ? aggregationImg : eventAggregationImg |
| | | const MapPopUpBox = type === 'device' ? DevicePopUpBox : EventPopUpBox |
| | | const styleTransform = type === 'device' ? 'translateY(-50%)' : 'translate(-50%,-110%)' |
| | | |
| | | let scalingJudgment = [ |
| | | { name: '县', splashedList: [], gJson: null, show: false, outline: {}, value: [0, 48651], height: 31753 }, |
| | | { name: '市', splashedList: [], gJson: null, show: false, outline: {}, value: [48651, 314863], height: 257731 }, |
| | | { |
| | | name: '省', |
| | | splashedList: [], |
| | | gJson: null, |
| | | show: false, |
| | | outline: {}, |
| | | value: [314863, 3796280000], |
| | | height: 1987280, |
| | | }, |
| | | ] |
| | | let viewer = null |
| | | let active = null |
| | | let handler = null |
| | | let currentEntity = null |
| | | let scalingJudgment = [ |
| | | { name: '县', splashedList: [], gJson: null, show: false, outline: {}, value: [0, 48651], height: 31753 }, |
| | | { name: '市', splashedList: [], gJson: null, show: false, outline: {}, value: [48651, 314863], height: 257731 }, |
| | | { |
| | | name: '省', |
| | | splashedList: [], |
| | | gJson: null, |
| | | show: false, |
| | | outline: {}, |
| | | value: [314863, 3796280000], |
| | | height: 1987280, |
| | | }, |
| | | ] |
| | | let viewer = null |
| | | let active = null |
| | | let handler = null |
| | | let currentEntity = null |
| | | |
| | | const store = useStore() |
| | | const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode) |
| | | const selectedAreaCode = computed(() => store.state.user.selectedAreaCode) |
| | | const store = useStore() |
| | | const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode) |
| | | const selectedAreaCode = computed(() => store.state.user.selectedAreaCode) |
| | | |
| | | const eventTimeType = computed(() => store.state.home.eventTimeType) |
| | | const eventTimeRang = computed(() => store.state.home.eventTimeRang) |
| | | |
| | | const eventTimeType = computed(() => store.state.home.eventTimeType) |
| | | const eventTimeRang = computed(() => store.state.home.eventTimeRang) |
| | | const singleUavHome = computed(() => store.state.home.singleUavHome) |
| | | |
| | | const singleUavHome = computed(() => store.state.home.singleUavHome) |
| | | let needFly = true |
| | | |
| | | let needFly = true |
| | | const combinedValues = computed(() => ({ |
| | | selectedAreaCode: selectedAreaCode.value, |
| | | eventTimeType: eventTimeType.value, |
| | | eventTimeRang: eventTimeRang.value, |
| | | singleUavHome: singleUavHome.value, |
| | | })) |
| | | |
| | | const combinedValues = computed(() => ({ |
| | | selectedAreaCode: selectedAreaCode.value, |
| | | eventTimeType: eventTimeType.value, |
| | | eventTimeRang: eventTimeRang.value, |
| | | singleUavHome: singleUavHome.value, |
| | | })) |
| | | let saveParams = { area_code: '', date_enum: 'CURRENT_WEEK' } |
| | | |
| | | let saveParams = { area_code: '', date_enum: 'CURRENT_WEEK' } |
| | | // 确定缩放比例 |
| | | const determineScaling = () => { |
| | | // console.log('确定缩放比例'); |
| | | if (!viewer) return |
| | | let height = viewer.camera.positionCartographic.height |
| | | // 根据高度展示对应的 gJson |
| | | for (let [index, item] of scalingJudgment.entries()) { |
| | | if (!item.show) return |
| | | if (height > item.value[0] && height <= item.value[1]) { |
| | | if (active === item.name) return |
| | | active = item.name |
| | | removeEntities() |
| | | removeLabel() |
| | | renderOutline(item) |
| | | if (!item.gJson && !item.splashedList?.length) return |
| | | item.gJson ? aggregation(item) : splashed(item) |
| | | break |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 转换为目录结构, 返回数组, |
| | | function convertToHierarchy(code) { |
| | | const codeStr = code.toString() |
| | | const provinceCode = codeStr.slice(0, 2) + '0000' |
| | | const cityCode = codeStr.slice(0, 4) + '00' |
| | | if (codeStr.slice(2, 4) === '00' && codeStr.slice(4, 6) === '00') { |
| | | return [provinceCode] |
| | | } else if (codeStr.slice(4, 6) === '00') { |
| | | return [provinceCode, cityCode] |
| | | } |
| | | return [provinceCode, cityCode, code] |
| | | } |
| | | |
| | | // 确定缩放比例 |
| | | const determineScaling = () => { |
| | | // console.log('确定缩放比例'); |
| | | if (!viewer) return |
| | | let height = viewer.camera.positionCartographic.height |
| | | // 根据高度展示对应的 gJson |
| | | for (let [index, item] of scalingJudgment.entries()) { |
| | | if (!item.show) return |
| | | if (height > item.value[0] && height <= item.value[1]) { |
| | | if (active === item.name) return |
| | | active = item.name |
| | | removeEntities() |
| | | removeLabel() |
| | | renderOutline(item) |
| | | if (!item.gJson && !item.splashedList?.length) return |
| | | item.gJson ? aggregation(item) : splashed(item) |
| | | break |
| | | } |
| | | } |
| | | } |
| | | // 获取设备聚合 |
| | | function getDeviceCount(areaCode) { |
| | | return getDeviceRegionCount({ areaCode }).then(res => { |
| | | return res?.data?.data || [] |
| | | }) |
| | | } |
| | | // 获取设备散点 |
| | | function getDeviceList(areaCode) { |
| | | return getDeviceRegion({ areaCode }).then(res => { |
| | | |
| | | return (res?.data?.data || []).map(i => ({ ...i, type })) |
| | | |
| | | // 转换为目录结构, 返回数组, |
| | | function convertToHierarchy (code) { |
| | | const codeStr = code.toString() |
| | | const provinceCode = codeStr.slice(0, 2) + '0000' |
| | | const cityCode = codeStr.slice(0, 4) + '00' |
| | | if (codeStr.slice(2, 4) === '00' && codeStr.slice(4, 6) === '00') { |
| | | return [provinceCode] |
| | | } else if (codeStr.slice(4, 6) === '00') { |
| | | return [provinceCode, cityCode] |
| | | } |
| | | return [provinceCode, cityCode, code] |
| | | } |
| | | |
| | | }) |
| | | } |
| | | |
| | | // 获取设备聚合 |
| | | function getDeviceCount (areaCode) { |
| | | return getDeviceRegionCount({ areaCode }).then(res => { |
| | | return (res?.data?.data || []) |
| | | }) |
| | | } |
| | | // 获取设备散点 |
| | | function getDeviceList (areaCode) { |
| | | return getDeviceRegion({ areaCode }).then(res => { |
| | | return (res?.data?.data || []).map(i => ({ ...i, type })) |
| | | }) |
| | | } |
| | | // 事件散点 |
| | | let eventList = [] |
| | | function processChildren(childrens) { |
| | | // console.log(childrens, '事件点') |
| | | return (childrens || []).map(item => { |
| | | const arr = processChildren(item.childrens) |
| | | if (item.data) { |
| | | eventList = eventList.concat(item.data) |
| | | } |
| | | const returnObj = { |
| | | total_device_count: item.number, |
| | | region_code: item.id, |
| | | region_name: item.name, |
| | | } |
| | | if (arr.length !== 0) { |
| | | returnObj.childrens = arr |
| | | } |
| | | return returnObj |
| | | }) |
| | | } |
| | | |
| | | // 事件散点 |
| | | let eventList = [] |
| | | function processChildren (childrens) { |
| | | // console.log(childrens, '事件点') |
| | | return (childrens || []).map(item => { |
| | | const arr = processChildren(item.childrens) |
| | | if (item.data) { |
| | | eventList = eventList.concat(item.data) |
| | | } |
| | | const returnObj = { |
| | | total_device_count: item.number, |
| | | region_code: item.id, |
| | | region_name: item.name, |
| | | } |
| | | if (arr.length !== 0) { |
| | | returnObj.childrens = arr |
| | | } |
| | | return returnObj |
| | | }) |
| | | } |
| | | // 获取事件聚合 |
| | | function getMapEventCount(params) { |
| | | return getMapEvents(params).then(res => { |
| | | const resData = res?.data?.data |
| | | if (resData?.data) { |
| | | eventList = resData?.data |
| | | return [] |
| | | } |
| | | return processChildren(resData?.childrens) |
| | | }) |
| | | } |
| | | |
| | | // 获取事件聚合 |
| | | function getMapEventCount (params) { |
| | | return getMapEvents(params).then(res => { |
| | | const resData = res?.data?.data |
| | | if (resData?.data) { |
| | | eventList = resData?.data |
| | | return [] |
| | | } |
| | | return processChildren(resData?.childrens) |
| | | }) |
| | | } |
| | | const findFun = (featItem, numItem) => Number(featItem.region_code.slice(0, 6)) === numItem.properties.adcode |
| | | const { VITE_APP_BASE, VITE_APP_ENV } = import.meta.env |
| | | const defaultDir = `${VITE_APP_BASE}${VITE_APP_ENV === 'development' ? 'public/' : ''}geoJson/100000/` |
| | | |
| | | const findFun = (featItem, numItem) => Number(featItem.region_code.slice(0, 6)) === numItem.properties.adcode |
| | | const { VITE_APP_BASE, VITE_APP_ENV } = import.meta.env |
| | | const defaultDir = `${VITE_APP_BASE}${VITE_APP_ENV === 'development' ? 'public/' : ''}geoJson/100000/` |
| | | const getFiler = async url => { |
| | | const res = await fetch(url) |
| | | return await res.json() |
| | | } |
| | | const getOutLine = async (jsonPathPre, hierarchy) => { |
| | | const parentGJson = await getFiler(`${defaultDir}${jsonPathPre}/index.json`) |
| | | let features = parentGJson.features.find(item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1])) |
| | | return { type: 'FeatureCollection', features: [features] } |
| | | } |
| | | |
| | | const getFiler = async url => { |
| | | const res = await fetch(url) |
| | | return await res.json() |
| | | } |
| | | const getOutLine = async (jsonPathPre, hierarchy) => { |
| | | const parentGJson = await getFiler(`${defaultDir}${jsonPathPre}/index.json`) |
| | | let features = parentGJson.features.find( |
| | | item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1]) |
| | | ) |
| | | return { type: 'FeatureCollection', features: [features] } |
| | | } |
| | | const injectData = (gJson, dataList) => { |
| | | return { |
| | | ...gJson, |
| | | features: gJson.features.map(item => { |
| | | const findData = dataList.find(item1 => findFun(item1, item)) |
| | | return { ...item, data: { ...findData, type: type + 'Aggregation' } } |
| | | }), |
| | | } |
| | | } |
| | | |
| | | const injectData = (gJson, dataList) => { |
| | | return { |
| | | ...gJson, |
| | | features: gJson.features.map(item => { |
| | | const findData = dataList.find(item1 => findFun(item1, item)) |
| | | return { ...item, data: { ...findData, type: type + 'Aggregation' } } |
| | | }), |
| | | } |
| | | } |
| | | const initMapData = async areaCode => { |
| | | eventList = [] |
| | | if (!areaCode) return |
| | | saveParams.area_code = areaCode |
| | | const list = type === 'device' ? await getDeviceCount(areaCode) : await getMapEventCount(saveParams) |
| | | const splashedList = |
| | | type === 'device' |
| | | ? await getDeviceList(areaCode) |
| | | : eventList.map(i => ({ |
| | | eventId: i.id, |
| | | latitude: Number(i.latitude), |
| | | longitude: Number(i.longitude), |
| | | type: 'event', |
| | | })) |
| | | const hierarchy = convertToHierarchy(areaCode.slice(0, 6)) |
| | | const jsonPath = hierarchy.join('/') |
| | | const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/') |
| | | scalingJudgment = scalingJudgment.map(item => ({ ...item, show: true })) |
| | | scalingJudgment[0].gJson = null |
| | | scalingJudgment[0].splashedList = splashedList |
| | | active = null |
| | | // 省 |
| | | if (hierarchy.length === 1) { |
| | | const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`) |
| | | const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`) |
| | | scalingJudgment[1].gJson = { |
| | | ...gJson1, |
| | | features: gJson1.features.map(item => { |
| | | const findData = list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)) |
| | | return { ...item, data: { ...findData, type: type + 'Aggregation' } } |
| | | }), |
| | | } |
| | | scalingJudgment[2].gJson = injectData(gJson2, list) |
| | | } |
| | | // 市 |
| | | if (hierarchy.length === 2) { |
| | | scalingJudgment[2].gJson = null |
| | | scalingJudgment[2].show = false |
| | | const gJson1 = await getFiler(`${defaultDir}${jsonPath}/index.json`) |
| | | scalingJudgment[1].gJson = injectData(gJson1, list) |
| | | } |
| | | // 区县 |
| | | if (hierarchy.length === 3) { |
| | | scalingJudgment[1].gJson = null |
| | | scalingJudgment[1].show = false |
| | | scalingJudgment[2].gJson = null |
| | | scalingJudgment[2].show = false |
| | | } |
| | | // 轮廓 |
| | | const outlineGJson = await getOutLine(jsonPathPre, hierarchy) |
| | | scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson)) |
| | | const [longitude, latitude] = outlineGJson.features[0].properties.centroid |
| | | const height = scalingJudgment[(hierarchy.length - 3) * -1].height |
| | | setCenterPosition({ longitude, latitude, height }) |
| | | flyTo({ longitude, latitude }, 0, height) |
| | | } |
| | | |
| | | const initMapData = async areaCode => { |
| | | eventList = [] |
| | | if (!areaCode) return |
| | | saveParams.area_code = areaCode |
| | | const list = type === 'device' ? await getDeviceCount(areaCode) : await getMapEventCount(saveParams) |
| | | const splashedList = type === 'device' |
| | | ? await getDeviceList(areaCode) |
| | | : eventList.map(i => ({ eventId: i.id, latitude: Number(i.latitude), longitude: Number(i.longitude), type: 'event' })) |
| | | const hierarchy = convertToHierarchy(areaCode.slice(0, 6)) |
| | | const jsonPath = hierarchy.join('/') |
| | | const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/') |
| | | scalingJudgment = scalingJudgment.map(item => ({ ...item, show: true })) |
| | | scalingJudgment[0].gJson = null |
| | | scalingJudgment[0].splashedList = splashedList |
| | | active = null |
| | | // 省 |
| | | if (hierarchy.length === 1) { |
| | | const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`) |
| | | const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`) |
| | | scalingJudgment[1].gJson = { |
| | | ...gJson1, |
| | | features: gJson1.features.map(item => { |
| | | const findData = list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)) |
| | | return { ...item, data: { ...findData, type: type + 'Aggregation' } } |
| | | }), |
| | | } |
| | | scalingJudgment[2].gJson = injectData(gJson2, list) |
| | | } |
| | | // 市 |
| | | if (hierarchy.length === 2) { |
| | | scalingJudgment[2].gJson = null |
| | | scalingJudgment[2].show = false |
| | | const gJson1 = await getFiler(`${defaultDir}${jsonPath}/index.json`) |
| | | scalingJudgment[1].gJson = injectData(gJson1, list) |
| | | } |
| | | // 区县 |
| | | if (hierarchy.length === 3) { |
| | | scalingJudgment[1].gJson = null |
| | | scalingJudgment[1].show = false |
| | | scalingJudgment[2].gJson = null |
| | | scalingJudgment[2].show = false |
| | | } |
| | | // 轮廓 |
| | | const outlineGJson = await getOutLine(jsonPathPre, hierarchy) |
| | | scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson)) |
| | | const [longitude, latitude] = outlineGJson.features[0].properties.centroid |
| | | const height = scalingJudgment[(hierarchy.length - 3) * (-1)].height |
| | | setCenterPosition({ longitude, latitude, height }) |
| | | flyTo({ longitude, latitude }, 0, height) |
| | | } |
| | | const userAreaPosition = computed(() => store.state.home.userAreaPosition) |
| | | |
| | | const userAreaPosition = computed(() => store.state.home.userAreaPosition) |
| | | const setCenterPosition = position => { |
| | | store.commit('setCurrentAreaPosition', position) |
| | | if (!userAreaPosition.value.longitude) { |
| | | store.commit('setUserAreaPosition', position) |
| | | } |
| | | } |
| | | |
| | | const setCenterPosition = (position) => { |
| | | store.commit('setCurrentAreaPosition', position) |
| | | if (!userAreaPosition.value.longitude) { |
| | | store.commit('setUserAreaPosition', position) |
| | | } |
| | | } |
| | | watch( |
| | | combinedValues, |
| | | async (newValue, oldValue) => { |
| | | if (newValue.singleUavHome?.device_sn) { |
| | | clearMapEntity() |
| | | return |
| | | } |
| | | |
| | | watch(combinedValues, async (newValue, oldValue) => { |
| | | if (newValue.singleUavHome?.device_sn) { |
| | | clearMapEntity() |
| | | return |
| | | } |
| | | if (newValue.eventTimeType) { |
| | | saveParams = { area_code: newValue.selectedAreaCode, date_enum: store.state.home.eventTimeParams } |
| | | } |
| | | |
| | | if (newValue.eventTimeType) { |
| | | saveParams = { area_code: newValue.selectedAreaCode, date_enum: store.state.home.eventTimeParams } |
| | | } |
| | | if (newValue.eventTimeRang) { |
| | | saveParams = { |
| | | area_code: newValue.selectedAreaCode, |
| | | start_date: newValue.eventTimeRang[0], |
| | | end_date: newValue.eventTimeRang[1], |
| | | } |
| | | } |
| | | |
| | | if (newValue.eventTimeRang) { |
| | | saveParams = { area_code: newValue.selectedAreaCode, start_date: newValue.eventTimeRang[0], end_date: newValue.eventTimeRang[1] } |
| | | } |
| | | needFly = true |
| | | if (!viewer) return |
| | | handlerInit() |
| | | |
| | | needFly = true |
| | | if (!viewer) return |
| | | handlerInit() |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | initMapData(newValue.selectedAreaCode).then(() => { |
| | | viewer.scene.postRender.addEventListener(determineScaling) |
| | | }) |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | initMapData(newValue.selectedAreaCode).then(() => { |
| | | viewer.scene.postRender.addEventListener(determineScaling) |
| | | }) |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | //散点机巢 |
| | | function splashed(row) { |
| | | row.splashedList.forEach((item, index) => { |
| | | |
| | | //散点机巢 |
| | | function splashed (row) { |
| | | row.splashedList.forEach((item, index) => { |
| | | viewer.entities.add({ |
| | | id: `aggregation-splashed-${index}`, |
| | | position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude), |
| | | label: { |
| | | text: item.nickname, |
| | | font: '12pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.WHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | outlineWidth: 2, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -9), |
| | | }, |
| | | billboard: { |
| | | image: new Cesium.ConstantProperty(singleImg), |
| | | width: 24, |
| | | height: 24, |
| | | }, |
| | | properties: { |
| | | customData: { |
| | | data: item, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | } |
| | | viewer.entities.add({ |
| | | id: `aggregation-splashed-${index}`, |
| | | position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude), |
| | | label: { |
| | | text: item.nickname, |
| | | font: '12pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.WHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | outlineWidth: 2, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -9), |
| | | }, |
| | | billboard: { |
| | | // singleImg |
| | | image: new Cesium.ConstantProperty(()=>{ |
| | | return item.status ==="OFFLINE" ? offlinesingleImg:singleImg |
| | | }), |
| | | width: 24, |
| | | height: 24, |
| | | }, |
| | | properties: { |
| | | customData: { |
| | | data: item, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 渲染轮廓 |
| | | const renderOutline = item => { |
| | | item.outline && |
| | | Cesium.GeoJsonDataSource.load(item.outline).then(dataSource => { |
| | | const entities = dataSource.entities.values |
| | | entities.forEach((entity, index) => { |
| | | // 创建独立折线作为轮廓 |
| | | const positions = entity.polygon.hierarchy.getValue().positions |
| | | const randomInt = Math.floor(Math.random() * 5) + 1 |
| | | // 渲染轮廓 |
| | | const renderOutline = item => { |
| | | item.outline && |
| | | Cesium.GeoJsonDataSource.load(item.outline).then(dataSource => { |
| | | const entities = dataSource.entities.values |
| | | entities.forEach((entity, index) => { |
| | | // 创建独立折线作为轮廓 |
| | | const positions = entity.polygon.hierarchy.getValue().positions |
| | | const randomInt = Math.floor(Math.random() * 5) + 1 |
| | | |
| | | let polygon = {} |
| | | let polygon = {} |
| | | |
| | | if (item.name === '县') { |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(arrColor[randomInt]), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3 |
| | | }) |
| | | if (item.name === '县') { |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(arrColor[randomInt]), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3, |
| | | }) |
| | | |
| | | entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || 1) * 500 |
| | | entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || 1) * 500 |
| | | |
| | | entity.polygon.material = material |
| | | entity.polygon.material = material |
| | | |
| | | polygon = entity.polygon |
| | | entity.polygon.outline = false // 显示边框 |
| | | } |
| | | polygon = entity.polygon |
| | | entity.polygon.outline = false // 显示边框 |
| | | } |
| | | |
| | | viewer.entities.add({ |
| | | id: `aggregation-outline-${index}`, |
| | | polyline: { |
| | | positions: positions, |
| | | width: 5, // 直接设置宽度 |
| | | material: new Cesium.PolylineGlowMaterialProperty({ |
| | | glowPower: 0.5, |
| | | color: Cesium.Color.AQUA, |
| | | }), |
| | | }, |
| | | viewer.entities.add({ |
| | | id: `aggregation-outline-${index}`, |
| | | polyline: { |
| | | positions: positions, |
| | | width: 5, // 直接设置宽度 |
| | | material: new Cesium.PolylineGlowMaterialProperty({ |
| | | glowPower: 0.5, |
| | | color: Cesium.Color.AQUA, |
| | | }), |
| | | }, |
| | | |
| | | polygon |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | polygon, |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 聚合机巢 |
| | | const aggregation = (item) => { |
| | | if (!item.gJson) return |
| | | const featuresList = item.gJson.features.map(item1 => { |
| | | // const {lng,lat} = getCenterPoint(item1.geometry.coordinates[0][0]) |
| | | return { |
| | | name: item1.properties.name, |
| | | position: item1.properties.centroid, |
| | | data: item1.data, |
| | | id: item1.region_code, |
| | | } |
| | | }) |
| | | // 遍历特征并添加实体 |
| | | featuresList.forEach((feature, index) => { |
| | | if (!feature.position) return |
| | | const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1], 0) |
| | | viewer.entities.add({ |
| | | position: position, |
| | | id: `aggregation-name-${index}`, |
| | | label: { |
| | | text: feature.name, |
| | | font: '14pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.WHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | outlineWidth: 2, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -9), |
| | | }, |
| | | }) |
| | | viewer.entities.add({ |
| | | id: `aggregation-count-${index}`, |
| | | position: position, |
| | | label: { |
| | | text: (feature.data.total_device_count || 0).toString(), |
| | | font: '12pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.BLACK, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面 |
| | | }, |
| | | billboard: { |
| | | image: new Cesium.ConstantProperty(mergeImg), |
| | | width: 35, |
| | | height: 35, |
| | | }, |
| | | properties: { |
| | | id: feature.id, |
| | | customData: { |
| | | data: feature.data, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | // 聚合机巢 |
| | | const aggregation = item => { |
| | | if (!item.gJson) return |
| | | const featuresList = item.gJson.features.map(item1 => { |
| | | // const {lng,lat} = getCenterPoint(item1.geometry.coordinates[0][0]) |
| | | return { |
| | | name: item1.properties.name, |
| | | position: item1.properties.centroid, |
| | | data: item1.data, |
| | | id: item1.region_code, |
| | | } |
| | | }) |
| | | // 遍历特征并添加实体 |
| | | featuresList.forEach((feature, index) => { |
| | | if (!feature.position) return |
| | | const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1], 0) |
| | | viewer.entities.add({ |
| | | position: position, |
| | | id: `aggregation-name-${index}`, |
| | | label: { |
| | | text: feature.name, |
| | | font: '14pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.WHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | outlineWidth: 2, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -9), |
| | | }, |
| | | }) |
| | | viewer.entities.add({ |
| | | id: `aggregation-count-${index}`, |
| | | position: position, |
| | | label: { |
| | | text: (feature.data.total_device_count || 0).toString(), |
| | | font: '12pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.BLACK, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面 |
| | | }, |
| | | billboard: { |
| | | image: new Cesium.ConstantProperty(mergeImg), |
| | | width: 35, |
| | | height: 35, |
| | | }, |
| | | properties: { |
| | | id: feature.id, |
| | | customData: { |
| | | data: feature.data, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | |
| | | // 加载边界 |
| | | Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => { |
| | | viewer.dataSources.add(dataSource) |
| | | item.BJDataSource = dataSource // 保存数据源以便后续删除 |
| | | // 获取数据源中的实体 |
| | | const entities = dataSource.entities.values |
| | | // 加载边界 |
| | | Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => { |
| | | viewer.dataSources.add(dataSource) |
| | | item.BJDataSource = dataSource // 保存数据源以便后续删除 |
| | | // 获取数据源中的实体 |
| | | const entities = dataSource.entities.values |
| | | |
| | | entities.forEach(entity => { |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(getColor()), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3 |
| | | }) |
| | | entities.forEach(entity => { |
| | | let material = new PolyGradientMaterial({ |
| | | color: Cesium.Color.fromCssColorString(getColor()), |
| | | opacity: 0.7, |
| | | alphaPower: 1.3, |
| | | }) |
| | | |
| | | const randomInt = Math.floor(Math.random() * 8) + 1 |
| | | const randomInt = Math.floor(Math.random() * 8) + 1 |
| | | |
| | | entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || randomInt) * 500 |
| | | entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || randomInt) * 500 |
| | | |
| | | entity.polygon.material = material |
| | | entity.polygon.outline = false // 显示边框 |
| | | }) |
| | | entity.polygon.material = material |
| | | entity.polygon.outline = false // 显示边框 |
| | | }) |
| | | |
| | | needFly && viewer.flyTo(dataSource, { |
| | | offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-60), 0), |
| | | duration: 0.5, |
| | | }) |
| | | needFly = false |
| | | }) |
| | | } |
| | | needFly && |
| | | viewer.flyTo(dataSource, { |
| | | offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-60), 0), |
| | | duration: 0.5, |
| | | }) |
| | | needFly = false |
| | | }) |
| | | } |
| | | |
| | | // 获取弹框box |
| | | const getLabelDom = data => { |
| | | const vNode = h(MapPopUpBox, { data, removeLabel }) |
| | | const tooltipContainer = document.createElement('div') |
| | | tooltipContainer.id = 'mapPopUpBox' |
| | | tooltipContainer.style.position = 'absolute' |
| | | tooltipContainer.style.transform = styleTransform |
| | | tooltipContainer.style.pointerEvents = 'none' |
| | | document.querySelector('.page-index').append(tooltipContainer) |
| | | render(vNode, tooltipContainer) |
| | | return tooltipContainer |
| | | } |
| | | // 获取弹框box |
| | | const getLabelDom = data => { |
| | | const vNode = h(MapPopUpBox, { data, removeLabel }) |
| | | const tooltipContainer = document.createElement('div') |
| | | tooltipContainer.id = 'mapPopUpBox' |
| | | tooltipContainer.style.position = 'absolute' |
| | | tooltipContainer.style.transform = styleTransform |
| | | tooltipContainer.style.pointerEvents = 'none' |
| | | document.querySelector('.page-index').append(tooltipContainer) |
| | | render(vNode, tooltipContainer) |
| | | return tooltipContainer |
| | | } |
| | | |
| | | // 弹框位置刷新 |
| | | const labelBoxRender = () => { |
| | | if (!currentEntity) return |
| | | let dom = document.querySelector('#mapPopUpBox') |
| | | if (!dom) { |
| | | dom = getLabelDom(currentEntity.properties.customData._value.data) |
| | | } |
| | | const screenPosition = viewer.scene.cartesianToCanvasCoordinates(currentEntity?.position?._value) |
| | | if (screenPosition) { |
| | | dom.style.left = `${screenPosition.x}px` |
| | | dom.style.top = `${screenPosition.y}px` |
| | | dom.style.display = 'block' |
| | | } |
| | | } |
| | | // 弹框位置刷新 |
| | | const labelBoxRender = () => { |
| | | if (!currentEntity) return |
| | | let dom = document.querySelector('#mapPopUpBox') |
| | | if (!dom) { |
| | | dom = getLabelDom(currentEntity.properties.customData._value.data) |
| | | } |
| | | const screenPosition = viewer.scene.cartesianToCanvasCoordinates(currentEntity?.position?._value) |
| | | if (screenPosition) { |
| | | dom.style.left = `${screenPosition.x}px` |
| | | dom.style.top = `${screenPosition.y}px` |
| | | dom.style.display = 'block' |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据条件获取项 |
| | | * @param {Array} arr 数据源 |
| | | * @param {Function} condition 条件 |
| | | * @returns |
| | | */ |
| | | const findTypeItem = (arr, condition) => { |
| | | return arr.find(item => condition(item)) |
| | | } |
| | | /** |
| | | * 根据条件获取项 |
| | | * @param {Array} arr 数据源 |
| | | * @param {Function} condition 条件 |
| | | * @returns |
| | | */ |
| | | const findTypeItem = (arr, condition) => { |
| | | return arr.find(item => condition(item)) |
| | | } |
| | | |
| | | // 左键单机事件 |
| | | const singleMachineEvent = async click => { |
| | | let clickTargets = viewer.scene.drillPick(click.position).map(item => item.id) |
| | | if (!clickTargets.length) return |
| | | // 左键单机事件 |
| | | const singleMachineEvent = async click => { |
| | | let clickTargets = viewer.scene.drillPick(click.position).map(item => item.id) |
| | | if (!clickTargets.length) return |
| | | |
| | | console.log(clickTargets, 11111) |
| | | // console.log(clickTargets, 11111) |
| | | |
| | | let deviceAggregationFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'deviceAggregation') |
| | | let deviceFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'device') |
| | | // "event" |
| | | let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'event') |
| | | // let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'eventAggregation') |
| | | currentEntity = deviceAggregationFind || deviceFind || eventFind |
| | | let deviceAggregationFind = findTypeItem( |
| | | clickTargets, |
| | | item => item?.properties?.customData?._value?.data?.type === 'deviceAggregation' |
| | | ) |
| | | let deviceFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'device') |
| | | // "event" |
| | | let eventFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'event') |
| | | // let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'eventAggregation') |
| | | currentEntity = deviceAggregationFind || deviceFind || eventFind |
| | | |
| | | if (!currentEntity) return |
| | | if (!currentEntity?.position?._value) return |
| | | // 一定要移除 |
| | | removeLabel() |
| | | if (deviceAggregationFind || eventFind) { |
| | | viewer.scene.postRender.addEventListener(labelBoxRender) |
| | | } |
| | | if (deviceFind) { |
| | | const device = deviceFind.properties.customData._value.data |
| | | store.commit('setSingleUavHome', device) |
| | | } |
| | | } |
| | | if (!currentEntity) return |
| | | if (!currentEntity?.position?._value) return |
| | | // 一定要移除 |
| | | removeLabel() |
| | | if (deviceAggregationFind || eventFind) { |
| | | viewer.scene.postRender.addEventListener(labelBoxRender) |
| | | } |
| | | if (deviceFind) { |
| | | const device = deviceFind.properties.customData._value.data |
| | | store.commit('setSingleUavHome', device) |
| | | } |
| | | } |
| | | |
| | | const removeDom = () => { |
| | | const dom = document.querySelector('#mapPopUpBox') |
| | | if (dom && dom.parentNode) { |
| | | dom.parentNode.removeChild(dom) |
| | | } |
| | | } |
| | | const removeDom = () => { |
| | | const dom = document.querySelector('#mapPopUpBox') |
| | | if (dom && dom.parentNode) { |
| | | dom.parentNode.removeChild(dom) |
| | | } |
| | | } |
| | | |
| | | // 移除 点 和 gjson 实体 |
| | | const removeEntities = () => { |
| | | // dataSources移除 |
| | | scalingJudgment.forEach(item => { |
| | | item.BJDataSource && viewer.dataSources.remove(item.BJDataSource) |
| | | item.BJDataSource = null |
| | | }) |
| | | // entities移除 |
| | | const entitiesIDs = viewer.entities.values.map(i => i.id) |
| | | entitiesIDs.forEach(item => { |
| | | item.includes('aggregation-') && viewer.entities.removeById(item) |
| | | }) |
| | | } |
| | | // 移除弹框标签 |
| | | const removeLabel = () => { |
| | | viewer?.scene.postRender.removeEventListener(labelBoxRender) |
| | | removeDom() |
| | | } |
| | | // 移除 点 和 gjson 实体 |
| | | const removeEntities = () => { |
| | | // dataSources移除 |
| | | scalingJudgment.forEach(item => { |
| | | item.BJDataSource && viewer.dataSources.remove(item.BJDataSource) |
| | | item.BJDataSource = null |
| | | }) |
| | | // entities移除 |
| | | const entitiesIDs = viewer.entities.values.map(i => i.id) |
| | | entitiesIDs.forEach(item => { |
| | | item.includes('aggregation-') && viewer.entities.removeById(item) |
| | | }) |
| | | } |
| | | // 移除弹框标签 |
| | | const removeLabel = () => { |
| | | viewer?.scene.postRender.removeEventListener(labelBoxRender) |
| | | removeDom() |
| | | } |
| | | |
| | | // 移除所有监听事件,变量置空 |
| | | const removeAll = () => { |
| | | clearMapEntity() |
| | | viewer = null |
| | | } |
| | | // 移除所有监听事件,变量置空 |
| | | const removeAll = () => { |
| | | clearMapEntity() |
| | | viewer = null |
| | | } |
| | | |
| | | const clearMapEntity = () => { |
| | | if (!viewer) return |
| | | removeEntities() |
| | | removeLabel() |
| | | // viewer.camera.moveEnd.removeEventListener(determineScaling); |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | handler?.destroy() |
| | | active = null |
| | | handler = null |
| | | currentEntity = null |
| | | } |
| | | const clearMapEntity = () => { |
| | | if (!viewer) return |
| | | removeEntities() |
| | | removeLabel() |
| | | // viewer.camera.moveEnd.removeEventListener(determineScaling); |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | handler?.destroy() |
| | | active = null |
| | | handler = null |
| | | currentEntity = null |
| | | } |
| | | |
| | | const init = () => { |
| | | viewer = window.$viewer |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | initMapData(selectedAreaCode.value || userAreaCode.value).then(() => { |
| | | viewer.scene.postRender.addEventListener(determineScaling) |
| | | }) |
| | | const init = () => { |
| | | viewer = window.$viewer |
| | | viewer.scene.postRender.removeEventListener(determineScaling) |
| | | initMapData(selectedAreaCode.value || userAreaCode.value).then(() => { |
| | | viewer.scene.postRender.addEventListener(determineScaling) |
| | | }) |
| | | |
| | | handlerInit() |
| | | } |
| | | handlerInit() |
| | | } |
| | | |
| | | const handlerInit = () => { |
| | | if (handler) return |
| | | const handlerInit = () => { |
| | | if (handler) return |
| | | |
| | | handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) |
| | | handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | } |
| | | handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) |
| | | handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | } |
| | | |
| | | onBeforeUnmount(() => { }) |
| | | // onMounted(() => { |
| | | // nextTick(() => { |
| | | // viewer = window.$viewer; |
| | | // handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); |
| | | // handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | // }); |
| | | // }); |
| | | onBeforeUnmount(() => {}) |
| | | // onMounted(() => { |
| | | // nextTick(() => { |
| | | // viewer = window.$viewer; |
| | | // handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); |
| | | // handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | // }); |
| | | // }); |
| | | |
| | | return { init, removeAll } |
| | | return { init, removeAll } |
| | | } |