| src/components/waylinetool/component/take-photo.vue | ●●●●● patch | view | raw | blame | history | |
| src/components/waylinetool/event-edit.vue | ●●●●● patch | view | raw | blame | history | |
| src/utils/cesium/mapUtils.ts | ●●●●● patch | view | raw | blame | history | |
| src/utils/cesium/use-kmz-tsa.ts | ●●●●● patch | view | raw | blame | history |
src/components/waylinetool/component/take-photo.vue
New file @@ -0,0 +1,235 @@ <!-- * @Author: GuLiMmo 2820890765@qq.com * @Date: 2024-03-27 15:15:50 * @LastEditors: GuLiMmo 2820890765@qq.com * @LastEditTime: 2024-03-27 17:31:10 * @FilePath: /drone-web/src/components/waylinetool/component/take-photo.vue * @Description: 航点事件-单拍 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved. --> <template> <div class="container"> <div :class="['fileSuffix', isInputShow && 'no-select']"> <span>DJI_YYYYMMDDhhmm_XXX_</span> <span class="icon" @click="isInputShow = !isInputShow"><EditOutlined /></span> </div> <div class="fileSuffix-input" v-if="isInputShow"> <a-input v-model:value="fileSuffix" placeholder="请输入文件后缀名称" size="small"></a-input> <a-button type="primary" shape="circle" size="small" @click="confirmInput"> <template #icon> <CheckOutlined /> </template> </a-button> <a-button type="danger" shape="circle" size="small" @click="cencalInput"> <template #icon> <CloseOutlined /> </template> </a-button> </div> <ul class="btn-group"> <li :class="[ 'btn', isGlobalPhotoFormat && 'disabled-btn', !defaultParams.payloadLensIndex?.['#text'].includes('wide') && 'no-btn-selected', ]" @click="!isGlobalPhotoFormat && addFormatEvent('wide')"> 广角照片 </li> <li :class="[ 'btn', isGlobalPhotoFormat && 'disabled-btn', !defaultParams.payloadLensIndex?.['#text'].includes('zoom') && 'no-btn-selected', ]" @click="!isGlobalPhotoFormat && addFormatEvent('zoom')"> 变焦照片 </li> <li :class="['btn', !isGlobalPhotoFormat && 'no-btn-selected']" @click="addFormatEvent('global')">跟随全局</li> </ul> </div> </template> <script lang="ts" setup> import { defineProps, ref } from 'vue' import { template as xmlJson } from '/@/utils/cesium/use-kmz-tsa' import { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue' import { message } from 'ant-design-vue' interface serialProp { placemark: number action: number } interface text { '#text': any } interface takePhoto { fileSuffix?: text payloadLensIndex: text payloadPositionIndex: text useGlobalPayloadLensIndex: text } const isInputShow = ref<boolean>(false) const fileSuffix = ref<string>('') const defaultParams = ref<takePhoto | any>({ fileSuffix: { '#text': null }, payloadLensIndex: { '#text': null }, payloadPositionIndex: { '#text': null }, useGlobalPayloadLensIndex: { '#text': null }, }) const confirmInput = () => { defaultParams.value.fileSuffix['#text'] = fileSuffix.value message.success('修改拍摄照片文件后缀成功!!') } const cencalInput = () => { fileSuffix.value = defaultFileSuffix.value message.success('恢复初始拍摄照片文件后缀成功!!') } const props = defineProps<{ serial: serialProp }>() const defaultFileSuffix = ref<string>('') const getDefaultParams = (serial: serialProp) => { const placemarkJson = xmlJson.value.Folder.Placemark[serial.placemark] let action = placemarkJson.actionGroup.action if (Array.isArray(action)) { action = action[serial.action] } const actionActuatorFuncParam = action.actionActuatorFuncParam defaultParams.value = actionActuatorFuncParam fileSuffix.value = actionActuatorFuncParam.fileSuffix['#text'] defaultFileSuffix.value = actionActuatorFuncParam.fileSuffix['#text'] isInputShow.value = !!defaultParams.value.fileSuffix } // 判断当前是否使用全局照片设置 const isGlobalPhotoFormat = computed(() => Number(defaultParams.value.useGlobalPayloadLensIndex['#text'])) // 照片格式 const addFormatEvent = (value: string) => { if (value === 'global') { defaultParams.value.useGlobalPayloadLensIndex['#text'] = Number(!isGlobalPhotoFormat.value) if (!isGlobalPhotoFormat.value) { defaultParams.value.payloadLensIndex = { '#text': 'zoom,wide' } } else { delete defaultParams.value.payloadLensIndex } } else { if (!defaultParams.value.payloadLensIndex) { defaultParams.value.payloadLensIndex = { '#text': '' } } const payloadLensIndex = defaultParams.value.payloadLensIndex['#text'] const payloadLensIndexArr = payloadLensIndex.split(',') if (!payloadLensIndex) { defaultParams.value.payloadLensIndex['#text'] = value } else { const index = payloadLensIndexArr.findIndex((item: string) => item === value) if (index === -1) { payloadLensIndexArr.push(value) } else { payloadLensIndexArr.splice(index, 1) } defaultParams.value.payloadLensIndex['#text'] = payloadLensIndexArr.join(',') } } } // 最新值 watch( () => defaultParams.value, (newParams) => { console.log(newParams) }, { deep: true, }, ) // 默认值 watch( () => props.serial, (newVal: serialProp) => { getDefaultParams(newVal) }, { deep: true, immediate: true, }, ) </script> <style lang="scss" scoped> .container { width: 100%; height: 100%; .fileSuffix { display: flex; align-items: center; justify-content: space-between; .icon { cursor: pointer; &:hover { color: #409eff; } } } .fileSuffix-input { margin-top: 10px; display: flex; input { background-color: transparent; color: #fff; } .ant-btn { margin-left: 10px; } } .btn-group { list-style-type: none; margin: 15px 0 0 0; padding: 0; display: flex; gap: 10px; justify-content: flex-start; .btn { font-size: 13px; padding: 2px 10px; background-color: #409eff; border-radius: 999px; cursor: pointer; font-weight: bold; &:last-child { margin-left: auto; } } } } .no-select { color: hsla(0, 0%, 100%, 0.45); } .no-btn-selected { background-color: hsla(0, 0%, 100%, 0.45) !important; border: hsla(0, 0%, 100%, 0.45) !important; } .disabled-btn { cursor: not-allowed !important; background-color: #314768 !important; border: #314768 !important; color: #ccc; } </style> src/components/waylinetool/event-edit.vue
@@ -12,34 +12,7 @@ </div> </div> <div class="event-edit"> <!-- 单拍 --> <template v-if="currentPointEvent.aciton.key === 'takePhoto'"> <div class="take-photo"> <div class="title"> <span :style="{ color: isTakePhotoNameShow || takePhotoSetting.fileSuffix ? 'rgba(255,255,255,0.4)' : '#fff', }" >DJI_YYYYMMDDhhmm_XXX_</span > <span @click="isTakePhotoNameShow = !isTakePhotoNameShow"><EditOutlined /></span> </div> <div class="title-name-input" v-if="isTakePhotoNameShow"> <div class="input"><a-input size="small" v-model:value="takePhotoSetting.fileSuffix"></a-input></div> <div class="btn"> <span class="check"><CheckOutlined /></span> <span class="close"><CloseOutlined /></span> </div> </div> <div class="photo-format"> <a-button type="primary" shape="round" size="small" @click="photoFormatClick('wide')">广角照片</a-button> <a-button type="primary" shape="round" size="small" @click="photoFormatClick('zoom')">变焦照片</a-button> <a-button type="primary" shape="round" size="small" @click="photoFormatClick('global')" >跟随全局</a-button > </div> </div> </template> <takePhoto v-model:serial="serial" v-if="currentPointEvent.aciton.key === 'takePhoto'" /> </div> </div> <div class="map-box"></div> @@ -48,10 +21,10 @@ <script lang="ts" setup> import _ from 'lodash' import { DeleteOutlined, EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue' import { DeleteOutlined } from '@ant-design/icons-vue' import { useMyStore } from '/@/store' import { actionList } from '/@/utils/cesium/use-map-draw' import { template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa' import takePhoto from './component/take-photo.vue' const store = useMyStore() // 事件编辑是否显示 @@ -87,51 +60,7 @@ } }) // 单拍 const isTakePhotoNameShow = ref<boolean>(false) const takePhotoSetting = reactive({ fileSuffix: '', payloadLensIndex: '', useGlobalPayloadLensIndex: 0, }) const photoFormatClick = (value: string) => { if (value === 'global') { takePhotoSetting.useGlobalPayloadLensIndex = 1 } else { let formats = takePhotoSetting.payloadLensIndex.split(',') const index = formats.findIndex((item: string) => item === value) if (index === -1) { if (takePhotoSetting.payloadLensIndex === '') { formats = [value] } else { formats.push(value) } } else { formats.splice(index, 1) } takePhotoSetting.payloadLensIndex = formats.join(',') } addActionParam(takePhotoSetting) } const handleDelAction = () => {} // 加入事件参数 const addActionParam = <T extends { [key: string] : string }, >(params: T): void => { const obj = _.cloneDeep(params) const placemarks = xmlTemplate.value.Folder.Placemark let aciton = placemarks[serial.placemark].actionGroup?.action if (Array.isArray(aciton)) { aciton = aciton[serial.action] } console.log(aciton) const actionActuatorFuncParam = aciton.actionActuatorFuncParam // Object.keys(obj).forEach((key: string) => { // if (!obj[key]) { // delete obj[key] // } // }) } </script> <style lang="scss" scoped> @@ -184,7 +113,7 @@ height: calc(100% - 50px); padding: 15px; overflow: auto; // 单排 // 单拍 .take-photo { .title { display: flex; @@ -230,19 +159,24 @@ } } } .photo-format { margin-top: 20px; display: flex; justify-content: flex-start; .ant-btn { margin-left: 10px; font-weight: bold; &:first-child { margin: 0; } &:nth-child(3) { margin-left: auto; } } .btn-group { margin-top: 20px; display: flex; justify-content: flex-start; button { margin-left: 10px; font-weight: bold; background-color: #409eff; border-radius: 999px; border: 0; padding: 0 10px 0 10px; &:first-child { margin: 0; } &:nth-child(3) { margin-left: auto; } } } src/utils/cesium/mapUtils.ts
@@ -57,7 +57,10 @@ } // 获取当前经纬度海拔 export const getHaeHeight = (start: { longitude: number; latitude: number; height: number }, end: { longitude: number; latitude: number; height: number }) => { export const getHaeHeight = ( start: { longitude: number; latitude: number; height: number }, end: { longitude: number; latitude: number; height: number }, ) => { const ellipsoid = Cesium.Ellipsoid.WGS84 // 选择合适的椭圆体模型 // const { longitude, latitude, height } = start // const { longitude: endLng, latitude: endLat, height: endHeight } = end @@ -74,3 +77,23 @@ const haeHeight = ellipsoid.cartesianToCartographic(cartesianPosition).height return haeHeight } // Cesium Cartesian3 转正常经纬度 export const cartesian3Convert = (cartesian3Position: Cesium.Cartesian3, viewer: { scene: { globe: { ellipsoid: any } } }) => { // 转换为经纬度 const ellipsoid = viewer.scene.globe.ellipsoid const cartographicPosition = Cesium.Cartographic.fromCartesian(cartesian3Position, ellipsoid) const longitude = Cesium.Math.toDegrees(cartographicPosition.longitude) const latitude = Cesium.Math.toDegrees(cartographicPosition.latitude) const height = cartographicPosition.height console.log('经度: ' + longitude) console.log('纬度: ' + latitude) console.log('高度: ' + height) return { longitude, latitude, height, } } src/utils/cesium/use-kmz-tsa.ts
@@ -82,6 +82,15 @@ }, }, ], payloadParam: { payloadPositionIndex: { '#text': 0 }, focusMode: { '#text': 'firstPoint' }, meteringMode: { '#text': 'average' }, returnMode: { '#text': 'singleReturnFirst' }, samplingRate: { '#text': '240000' }, scanningMode: { '#text': 'repetitive' }, imageFormat: { '#text': 'wide,zoom' } } }, }) const waylines = ref<any>({