useMapTrackPlayback.ts 2.88 KB
import { ShallowRef, computed, ref, shallowRef, unref } from 'vue';
import { TrackAnimationStatus } from './type';
import { useTimeoutFn } from '@vueuse/core';
import { useMessage } from '/@/hooks/web/useMessage';

export const useMapTrackPlayback = (mapInstance: ShallowRef<Nullable<Recordable>>) => {
  const { createMessage } = useMessage();

  const trackAni = ref<Nullable<Recordable>>(null);

  const playFn = shallowRef<Nullable<Fn>>(() => {
    trackAni.value?.start?.();
  });

  const pauseFn = shallowRef<Nullable<Fn>>(() => {
    trackAni.value?.pause?.();
  });

  const continueFn = shallowRef<Nullable<Fn>>(() => {
    trackAni.value?.continue?.();
  });

  const playStatus = computed<TrackAnimationStatus>(() => {
    return unref(trackAni)?._status;
  });

  const RANDOM_PATH = [
    {
      lng: 116.297611,
      lat: 40.047363,
    },
    {
      lng: 116.302839,
      lat: 40.048219,
    },
    {
      lng: 116.308301,
      lat: 40.050566,
    },
    {
      lng: 116.305732,
      lat: 40.054957,
    },
    {
      lng: 116.304754,
      lat: 40.057953,
    },
    {
      lng: 116.306487,
      lat: 40.058312,
    },
    {
      lng: 116.307223,
      lat: 40.056379,
    },
  ];

  const getAnimationDurationTime = (length: number) => {
    const itemDurationTime = 1000;
    const minDurationTime = 5000;
    const durationTime = length * itemDurationTime;
    return Math.max(durationTime, minDurationTime);
  };

  /**
   * @demo https://lbsyun.baidu.com/jsdemo.htm#fAnimationPause
   * @param path
   * @param clearOverlays
   */
  const genTrackPlaybackAnimation = (
    path?: Record<'lng' | 'lat', number>[],
    clearOverlays = true
  ) => {
    path = path || RANDOM_PATH;

    if (!path.length) {
      createMessage.warning('无可用数据~');
      return;
    }

    const point: any[] = [];
    const BMapGL = (window as any).BMapGL;

    clearOverlays && unref(mapInstance)?.clearOverlays();

    for (const { lng, lat } of path) {
      point.push(new BMapGL.Point(lng, lat));
    }

    const pl = new BMapGL.Polyline(point);
    const BMapGLLib = (window as any).BMapGLLib;

    for (const item of path) {
      marketPoint(item);
    }

    const duration = getAnimationDurationTime(path?.length || 0);
    const delay = 300;
    trackAni.value = new BMapGLLib.TrackAnimation(unref(mapInstance), pl, {
      overallView: true,
      tilt: 30,
      duration,
      delay,
    });

    useTimeoutFn(() => {
      unref(playFn)?.();
    }, 500);
  };

  function marketPoint(params: Partial<Record<'lng' | 'lat', number>>) {
    const { lng, lat } = params;
    if (![lng, lat].every(Boolean)) return;
    const BMap = (window as any).BMapGL;
    const marker = new BMap.Marker(new BMap.Point(lng, lat));
    unref(mapInstance)?.centerAndZoom(new BMap.Point(lng, lat));
    unref(mapInstance)?.addOverlay(marker);
  }

  return { genTrackPlaybackAnimation, playFn, pauseFn, continueFn, playStatus };
};