<template>
|
<div :id="mapId" class="common-cesium-map" @contextmenu.prevent></div>
|
</template>
|
|
<script setup>
|
import { onBeforeUnmount, onMounted, watch } from 'vue'
|
import { PublicCesium } from '@/utils/cesium/publicCesium'
|
import { loadJaAdminBoundary, removeJaAdminBoundary } from '@/utils/cesium/adminBoundary'
|
|
const props = defineProps({
|
active: {
|
type: Boolean,
|
default: true,
|
},
|
domId: {
|
type: String,
|
default: '',
|
},
|
flatMode: {
|
type: Boolean,
|
default: false,
|
},
|
terrain: {
|
type: Boolean,
|
default: true,
|
},
|
layerMode: {
|
type: Number,
|
default: 4,
|
},
|
boundary: {
|
type: Boolean,
|
default: false,
|
},
|
contour: {
|
type: Boolean,
|
default: false,
|
},
|
showAdminBoundary: {
|
type: Boolean,
|
default: true,
|
},
|
zoomToBoundary: {
|
type: Boolean,
|
default: true,
|
},
|
enableStageEmit: {
|
type: Boolean,
|
default: false,
|
},
|
clusterHeight: {
|
type: Number,
|
default: 100000,
|
},
|
detailHeight: {
|
type: Number,
|
default: 10000,
|
},
|
})
|
|
const emit = defineEmits(['ready', 'height-change', 'stage-change'])
|
const mapId = props.domId || `common-cesium-map-${Math.random().toString(36).slice(2, 10)}`
|
let viewInstance = null
|
let viewer = null
|
const ADMIN_BOUNDARY_NAMES = {
|
boundary: 'jaBoundarySource',
|
line: 'jaBoundaryLineSource',
|
label: 'jaBoundaryLabelSource',
|
}
|
let adminBoundarySources = null
|
let initialized = false
|
let removeCameraListener = null
|
|
const initMap = async () => {
|
if (initialized) return
|
initialized = true
|
viewInstance = new PublicCesium({
|
dom: mapId,
|
flatMode: props.flatMode,
|
terrain: props.terrain,
|
layerMode: props.layerMode,
|
boundary: props.boundary,
|
contour: props.contour,
|
})
|
viewer = viewInstance.getViewer()
|
if (props.showAdminBoundary) {
|
adminBoundarySources = await loadJaAdminBoundary(viewer, {
|
zoomTo: props.zoomToBoundary,
|
})
|
}
|
if (props.enableStageEmit) {
|
let lastStage = ''
|
const onCameraChanged = () => {
|
const height = viewer?.camera?.positionCartographic?.height
|
if (height == null) return
|
emit('height-change', height)
|
let stage = 'mid'
|
if (height >= props.clusterHeight) stage = 'cluster'
|
if (height <= props.detailHeight) stage = 'detail'
|
if (stage !== lastStage) {
|
lastStage = stage
|
emit('stage-change', stage)
|
}
|
}
|
viewer?.camera?.changed?.addEventListener(onCameraChanged)
|
removeCameraListener = () => viewer?.camera?.changed?.removeEventListener(onCameraChanged)
|
}
|
emit('ready', { viewer, publicCesium: viewInstance })
|
}
|
|
watch(
|
() => props.active,
|
active => {
|
if (active) initMap()
|
}
|
)
|
|
onMounted(() => {
|
if (props.active) initMap()
|
})
|
|
onBeforeUnmount(() => {
|
if (removeCameraListener) removeCameraListener()
|
removeJaAdminBoundary(viewer, adminBoundarySources)
|
adminBoundarySources = null
|
viewInstance?.viewerDestroy?.()
|
})
|
|
const setAdminBoundaryVisible = async visible => {
|
if (!viewer) return
|
const removeByNames = () => {
|
Object.values(ADMIN_BOUNDARY_NAMES).forEach(name => {
|
const sources = viewer.dataSources.getByName(name) || []
|
sources.forEach(source => viewer.dataSources.remove(source))
|
})
|
}
|
const resolveSources = () => {
|
if (adminBoundarySources) return adminBoundarySources
|
const boundarySource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.boundary)?.[0] ?? null
|
const lineSource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.line)?.[0] ?? null
|
const labelSource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.label)?.[0] ?? null
|
if (boundarySource || lineSource || labelSource) {
|
adminBoundarySources = { boundarySource, lineSource, labelSource }
|
}
|
return adminBoundarySources
|
}
|
const setVisible = (source, next) => {
|
if (!source) return
|
source.show = next
|
source.entities?.values?.forEach(entity => {
|
entity.show = next
|
})
|
}
|
const sources = resolveSources()
|
if (!visible) {
|
if (sources) {
|
removeJaAdminBoundary(viewer, sources)
|
adminBoundarySources = null
|
}
|
removeByNames()
|
return
|
}
|
if (sources) {
|
const { boundarySource, lineSource, labelSource } = sources
|
setVisible(boundarySource, true)
|
setVisible(lineSource, true)
|
setVisible(labelSource, true)
|
return
|
}
|
adminBoundarySources = await loadJaAdminBoundary(viewer, {
|
zoomTo: false,
|
})
|
}
|
|
const getMap = () => ({ viewer, publicCesium: viewInstance })
|
const getViewer = () => viewer
|
const getPublicCesium = () => viewInstance
|
|
defineExpose({ getMap, getViewer, getPublicCesium, setAdminBoundaryVisible })
|
</script>
|
|
<style scoped lang="scss">
|
.common-cesium-map {
|
width: 100%;
|
height: 100%;
|
}
|
</style>
|