| ... | ... | @@ -4,10 +4,8 @@ | 
| 4 | 4 | }; | 
| 5 | 5 | </script> | 
| 6 | 6 | <script lang="ts" setup> | 
| 7 |  | -  import { computed, nextTick, onMounted, ref, unref } from 'vue'; | 
|  | 7 | +  import { computed, onMounted, ref, unref } from 'vue'; | 
| 8 | 8 | import { RadioRecord } from '../../detail/config/util'; | 
| 9 |  | -  import { useScript } from '/@/hooks/web/useScript'; | 
| 10 |  | -  import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; | 
| 11 | 9 | import { MapComponentLayout, MapComponentValue } from './map.config'; | 
| 12 | 10 | import { | 
| 13 | 11 | ClockCircleOutlined, | 
| ... | ... | @@ -15,31 +13,107 @@ | 
| 15 | 13 | PauseCircleOutlined, | 
| 16 | 14 | } from '@ant-design/icons-vue'; | 
| 17 | 15 | import { Button, Tooltip } from 'ant-design-vue'; | 
|  | 16 | +  import { FrontComponent } from '../../const/const'; | 
|  | 17 | +  import { buildUUID } from '/@/utils/uuid'; | 
| 18 | 18 |  | 
| 19 |  | -  withDefaults( | 
|  | 19 | +  // useVisualBoardContext(); | 
|  | 20 | + | 
|  | 21 | +  const startMethodName = `trackPlayMethod_${buildUUID()}`; | 
|  | 22 | + | 
|  | 23 | +  const wrapId = `bai-map-${buildUUID()}`; | 
|  | 24 | + | 
|  | 25 | +  enum TrackAnimationStatus { | 
|  | 26 | +    PLAY = 1, | 
|  | 27 | +    DONE = 2, | 
|  | 28 | +    PAUSE = 3, | 
|  | 29 | +  } | 
|  | 30 | + | 
|  | 31 | +  const props = withDefaults( | 
| 20 | 32 | defineProps<{ | 
| 21 | 33 | value?: MapComponentValue; | 
| 22 | 34 | layout?: MapComponentLayout; | 
| 23 | 35 | radio?: RadioRecord; | 
|  | 36 | +      random?: boolean; | 
| 24 | 37 | }>(), | 
| 25 |  | -    {} | 
|  | 38 | +    { | 
|  | 39 | +      random: true, | 
|  | 40 | +    } | 
| 26 | 41 | ); | 
| 27 | 42 |  | 
| 28 | 43 | const wrapRef = ref<HTMLDivElement | null>(null); | 
| 29 |  | -  const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); | 
|  | 44 | +  const trackAni = ref<Nullable<any>>(null); | 
|  | 45 | +  let mapInstance: Nullable<Recordable> = null; | 
| 30 | 46 |  | 
| 31 | 47 | async function initMap() { | 
| 32 |  | -    await toPromise(); | 
| 33 |  | -    await nextTick(); | 
| 34 | 48 | const wrapEl = unref(wrapRef); | 
| 35 | 49 | if (!wrapEl) return; | 
| 36 |  | -    const BMap = (window as any).BMap; | 
| 37 |  | -    const map = new BMap.Map(wrapEl); | 
| 38 |  | -    const point = new BMap.Point(116.404, 39.915); | 
| 39 |  | -    map.centerAndZoom(point, 15); | 
| 40 |  | -    map.enableScrollWheelZoom(true); | 
|  | 50 | +    const BMapGL = (window as any).BMapGL; | 
|  | 51 | +    mapInstance = new BMapGL.Map(wrapId); | 
|  | 52 | +    const point = new BMapGL.Point(116.404, 39.915); | 
|  | 53 | +    mapInstance!.centerAndZoom(point, 15); | 
|  | 54 | +    mapInstance!.enableScrollWheelZoom(true); | 
|  | 55 | +    props.layout?.componentType === FrontComponent.MAP_COMPONENT_TRACK_HISTORY && randomAnimation(); | 
| 41 | 56 | } | 
| 42 | 57 |  | 
|  | 58 | +  const randomAnimation = () => { | 
|  | 59 | +    const path = [ | 
|  | 60 | +      { | 
|  | 61 | +        lng: 116.297611, | 
|  | 62 | +        lat: 40.047363, | 
|  | 63 | +      }, | 
|  | 64 | +      { | 
|  | 65 | +        lng: 116.302839, | 
|  | 66 | +        lat: 40.048219, | 
|  | 67 | +      }, | 
|  | 68 | +      { | 
|  | 69 | +        lng: 116.308301, | 
|  | 70 | +        lat: 40.050566, | 
|  | 71 | +      }, | 
|  | 72 | +      { | 
|  | 73 | +        lng: 116.305732, | 
|  | 74 | +        lat: 40.054957, | 
|  | 75 | +      }, | 
|  | 76 | +      { | 
|  | 77 | +        lng: 116.304754, | 
|  | 78 | +        lat: 40.057953, | 
|  | 79 | +      }, | 
|  | 80 | +      { | 
|  | 81 | +        lng: 116.306487, | 
|  | 82 | +        lat: 40.058312, | 
|  | 83 | +      }, | 
|  | 84 | +      { | 
|  | 85 | +        lng: 116.307223, | 
|  | 86 | +        lat: 40.056379, | 
|  | 87 | +      }, | 
|  | 88 | +    ]; | 
|  | 89 | + | 
|  | 90 | +    const point: any[] = []; | 
|  | 91 | +    const BMapGL = (window as any).BMapGL; | 
|  | 92 | + | 
|  | 93 | +    for (const { lng, lat } of path) { | 
|  | 94 | +      point.push(new BMapGL.Point(lng, lat)); | 
|  | 95 | +    } | 
|  | 96 | + | 
|  | 97 | +    const pl = new BMapGL.Polyline(point); | 
|  | 98 | +    const BMapGLLib = (window as any).BMapGLLib; | 
|  | 99 | + | 
|  | 100 | +    const dynamicPlayMethod = { | 
|  | 101 | +      [startMethodName]() { | 
|  | 102 | +        trackAni.value = new BMapGLLib.TrackAnimation(mapInstance, pl, { | 
|  | 103 | +          overallView: true, | 
|  | 104 | +          tilt: 30, | 
|  | 105 | +          duration: 20000, | 
|  | 106 | +          delay: 300, | 
|  | 107 | +        }); | 
|  | 108 | +        trackAni.value!.start(); | 
|  | 109 | +      }, | 
|  | 110 | +    }; | 
|  | 111 | + | 
|  | 112 | +    (window as any)[startMethodName] = dynamicPlayMethod[startMethodName]; | 
|  | 113 | + | 
|  | 114 | +    setTimeout(`${startMethodName}()`); | 
|  | 115 | +  }; | 
|  | 116 | + | 
| 43 | 117 | onMounted(() => { | 
| 44 | 118 | initMap(); | 
| 45 | 119 | }); | 
| ... | ... | @@ -50,20 +124,23 @@ | 
| 50 | 124 |  | 
| 51 | 125 | const handleTrackSwitch = () => {}; | 
| 52 | 126 |  | 
| 53 |  | -  const pauseFlag = ref(true); | 
|  | 127 | +  const getTrackPlayStatus = computed(() => { | 
|  | 128 | +    return (trackAni.value || {})._status; | 
|  | 129 | +  }); | 
| 54 | 130 |  | 
| 55 | 131 | const handlePlay = () => { | 
| 56 |  | -    pauseFlag.value = false; | 
| 57 |  | -  }; | 
| 58 |  | - | 
| 59 |  | -  const handlePause = () => { | 
| 60 |  | -    pauseFlag.value = true; | 
|  | 132 | +    if (unref(getTrackPlayStatus) === TrackAnimationStatus.DONE) unref(trackAni).start(); | 
|  | 133 | +    else if (unref(getTrackPlayStatus) === TrackAnimationStatus.PLAY) unref(trackAni).pause(); | 
|  | 134 | +    else if (unref(getTrackPlayStatus) === TrackAnimationStatus.PAUSE) unref(trackAni).continue(); | 
| 61 | 135 | }; | 
| 62 | 136 | </script> | 
| 63 | 137 |  | 
| 64 | 138 | <template> | 
| 65 | 139 | <div class="w-full h-full flex justify-center items-center flex-col"> | 
| 66 |  | -    <div class="w-[95%] flex"> | 
|  | 140 | +    <div | 
|  | 141 | +      class="w-full flex" | 
|  | 142 | +      v-if="props.layout?.componentType === FrontComponent.MAP_COMPONENT_TRACK_HISTORY" | 
|  | 143 | +    > | 
| 67 | 144 | <Button type="text" class="!px-2 flex-auto !text-left truncate" @click="handleTrackSwitch"> | 
| 68 | 145 | <div class="w-full truncate text-gray-500 flex items-center"> | 
| 69 | 146 | <ClockCircleOutlined /> | 
| ... | ... | @@ -75,15 +152,14 @@ | 
| 75 | 152 | </Tooltip> | 
| 76 | 153 | </div> | 
| 77 | 154 | </Button> | 
| 78 |  | -      <Button v-show="pauseFlag" type="text" class="!px-2 !text-gray-500" @click="handlePlay"> | 
| 79 |  | -        <PlayCircleOutlined /> | 
| 80 |  | -        <span>播放轨迹</span> | 
| 81 |  | -      </Button> | 
| 82 |  | -      <Button v-show="!pauseFlag" type="text" class="!px-2 !text-gray-500" @click="handlePause"> | 
| 83 |  | -        <PauseCircleOutlined /> | 
| 84 |  | -        <span>暂停播放</span> | 
|  | 155 | +      <Button type="text" class="!px-2 !text-gray-500" @click="handlePlay"> | 
|  | 156 | +        <PlayCircleOutlined v-show="getTrackPlayStatus !== TrackAnimationStatus.PLAY" /> | 
|  | 157 | +        <PauseCircleOutlined v-show="getTrackPlayStatus === TrackAnimationStatus.PLAY" /> | 
|  | 158 | +        <span> | 
|  | 159 | +          {{ getTrackPlayStatus !== TrackAnimationStatus.PLAY ? '播放轨迹' : '暂停播放' }} | 
|  | 160 | +        </span> | 
| 85 | 161 | </Button> | 
| 86 | 162 | </div> | 
| 87 |  | -    <div ref="wrapRef" class="w-[95%] h-[95%]"></div> | 
|  | 163 | +    <div ref="wrapRef" :id="wrapId" class="w-full h-full"></div> | 
| 88 | 164 | </div> | 
| 89 | 165 | </template> | 
... | ... |  |