maptalks 一些基础api的再封装(待解耦改装纯方法类)
maptalks 一些基础api的再封装(待解耦改装纯方法类)
浮川的小窝

maptalks 一些基础api的再封装(待解耦改装纯方法类)

面壁人浮川
2022-12-14 发布 / 正在检测是否收录...

20230515150327 (1).jpg

    import * as maptalks from "maptalks";
// import {
//   RoutePlayer,
//   getAllPointsArr,
// } from "^/assets/js/maptalks.routeplayer.es.js";
import { RoutePlayer } from "^/assets/js/maptalks.routeplayer.js";
import convertor from "chncrs";
import { createInfoWindow } from "^/composables/infoWindow";
import type {
  WSCarCoordinate,
  WSCarStatus,
  CarMarkerData,
  Coordinate,
  LineColor,
  InfoWindowCallback,
  ChangeModeCallback,
  AnimateiHstoryCarPath,
  InfoWindowData,
  MarkerLocation,
  BaseParameterData,
  DispatchMarker,
  AreaData,
} from "@/map";
import { infoWindowData } from "^/hook/infoWindow";
import utils from "^u/utils";
// 警车基础配置参数对象
import POLICE_CAR_CONFIG from "../../config/config";
import dispatchSvg from "^/assets/svg/icons/调度点-dispatch.svg";
import type { ElSkeleton } from "element-plus";

const HBmap_base_config = (
  cssFilter: string,
  spatialReference: any,
  tileSystem: any[]
) => ({
  urlTemplate: POLICE_CAR_CONFIG.MAP_URL,
  // 替换url中的子域 ?不是很理解
  subdomains: ["a", "b", "c", "d"],
  cssFilter,
  // 图片没出来 站位用的
  placeholder: true,
  // 平铺图像的 crossOrigin 跨域
  crossOrigin: "anonymous",
  // offset: offset as unknown as number[],
  //设置瓦片图层的空间参考spatialReference默认就是3857,googlemap的分辨率
  spatialReference,
  //tileSystem 控制瓦片的x,y以及行列,后两个是origin原点位置(很重要)
  tileSystem,
  // 是否启用此地图上光标样式图层的命中检测,禁用它以提高性能。(鼠标检测)
  hitDetect: false,
});
const GAODEmap_base_config = (
  cssFilter: string,
  spatialReference: any,
  tileSystem: any[]
) => ({
  // urlTemplate:
  //   "http://wprd{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&z={z}&x=&y={y}&scl=1&ltype=11",
  // // 替换url中的子域 ?不是很理解
  // subdomains: ["01", "02", "03", "04"],
  urlTemplate:
    "http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x=&y={y}&z={z}",
  subdomains: ["0", "1", "2", "3"],
  cssFilter,
  // 图片没出来 站位用的
  placeholder: true,
  // 平铺图像的 crossOrigin 跨域
  crossOrigin: "anonymous",
  // offset: offset as unknown as number[],
  //设置瓦片图层的空间参考spatialReference默认就是3857,googlemap的分辨率
  spatialReference,
  //tileSystem 控制瓦片的x,y以及行列,后两个是origin原点位置(很重要)
  tileSystem,
  // 是否启用此地图上光标样式图层的命中检测,禁用它以提高性能。(鼠标检测)
  hitDetect: false,
});

// 高德卫星图
const GAODEmap_satellite_base_config = (
  cssFilter: string,
  spatialReference: any,
  tileSystem: any[]
) => ({
  // urlTemplate:
  //   "http://wprd{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&z={z}&x=&y={y}&scl=1&ltype=11",
  // // 替换url中的子域 ?不是很理解
  // subdomains: ["01", "02", "03", "04"],
  urlTemplate:
    "https://webst01.is.autonavi.com/appmaptile?lang=zh_cn&style=6&x=&y={y}&z={z}",
  subdomains: ["0", "1", "2", "3"],
  cssFilter,
  // 图片没出来 站位用的
  placeholder: true,
  // 平铺图像的 crossOrigin 跨域
  crossOrigin: "anonymous",
  // offset: offset as unknown as number[],
  //设置瓦片图层的空间参考spatialReference默认就是3857,googlemap的分辨率
  spatialReference,
  //tileSystem 控制瓦片的x,y以及行列,后两个是origin原点位置(很重要)
  tileSystem,
  // 是否启用此地图上光标样式图层的命中检测,禁用它以提高性能。(鼠标检测)
  hitDetect: false,
});

interface Extentable {
  getExtent(): maptalks.Extent;
}

// 颜色转换
const colorToRGB = (color: string, opt: number) => {
    let color1, color2, color3;
    color = "" + color;
    if (typeof color !== "string") return;
    if (color.charAt(0) == "#") {
      color = color.substring(1);
    }
    if (color.length == 3) {
      color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2];
    }
    if (/^[0-9a-fA-F]{6}$/.test(color)) {
      color1 = parseInt(color.substr(0, 2), 16);
      color2 = parseInt(color.substr(2, 2), 16);
      color3 = parseInt(color.substr(4, 2), 16);
      return "rgba(" + color1 + "," + color2 + "," + color3 + "," + opt + ")";
    }
  },
  // 总体瓦片偏移,[dx, dy],对来自不同坐标系的瓦片源很有用,例如(wgs84 和 gcj02)
  // 底图不能重叠 这个是因为百度地图用的是bd09ll坐标系,
  // 天地图是cgcs2000坐标系,两个坐标系有偏转造成的。
  offset = (z: number) => {
    if (!this.map) return;
    const center = this.map.getCenter();
    const transformCenter = convertor.transform(
      center.toArray(),
      "gcj02",
      "wgs84"
    );
    targetCoordinate.set(transformCenter[0], transformCenter[1]);
    return this.map
      .coordToPoint(center, z, POINT0)
      .sub(this.map.coordToPoint(targetCoordinate, z, POINT1))
      .round()
      .toArray();
  };
// 全局绑定HBMap实例对象
let self: HBMap;

// 海博地图Base对象
export class HBMap {
  // map对象
  map: maptalks.Map;
  // 地图基础瓦片图层
  baseLayer: maptalks.TileLayer[] = [];
  // 点位图层
  markerLayer: maptalks.VectorLayer;
  // 轨迹图层
  trakLayer: maptalks.VectorLayer;
  // 调度图层 no
  dispatchLayer: maptalks.VectorLayer;
  // 区域图层 no
  areaLayer: maptalks.VectorLayer | null | undefined;
  // 网格图层 no
  gridLayer: maptalks.VectorLayer;
  // 车辆全量信息
  carsArr: CarMarkerData[] = [];
  // 车辆全量信息Map集合 yes
  carsMap: Map<string, CarMarkerData> = new Map();
  // 当前跟踪对象 yes
  followCarArr: string[] = [];
  // 当前点击车辆marker对象 yes
  currentCarMarker: CarMarkerData | null = null;
  // 全局所有车辆跟踪 no
  carFocus: boolean = false;
  // 选择点位模式 no
  coordinateLocationMode: boolean = false;
  // 当前点位信息 no
  DispatchMarkerMap: Map<string, MarkerLocation> = new Map();
  // 弹窗点击事件回调
  infoWindowCallback: InfoWindowCallback<CarMarkerData> | null = null;
  // 画点完毕回调
  changeModeCallback: ChangeModeCallback | null = null;
  /** 初始点位 */
  // eslint-disable-next-line no-loss-of-precision
  static InitialCoordinate: Coordinate = [120.38422855590826, 36.1354355861087];
  // [120.377365, 36.066538];
  /** 初始缩放等级 */
  static InitialZoom = 12.3;
  /** 点击车辆 缩放比例 */
  static InitialCarZoom = 15;
  /** 构造Coordinate */
  static Coordinate = maptalks.Coordinate;
  /** 弹窗最多个数 */
  static infoWindowNum = 5;
  constructor(
    renderer: HTMLElement,
    infoWindowCallback: InfoWindowCallback<CarMarkerData> | null,
    changeModeCallback: ChangeModeCallback | null
  ) {
    const center = HBMap.InitialCoordinate;
    self = this;
    /**
     *  WGS84:World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统
     *
     *  EPSG:4326 (WGS84) WGS84 是目前最流行的地理坐标系统。
     *   在国际上,每个坐标系统都会被分配一个 EPSG 代码,
     *   EPSG:4326 就是 WGS84 的代码。GPS是基于WGS84的,
     *   所以通常我们得到的坐标数据都是WGS84的。
     *   一般我们在存储数据时,仍然按WGS84存储
     *
     *  EPSG:3857 (Pseudo-Mercator) 伪墨卡托投影,也被称为球体墨卡托,
     *   Web Mercator它是基于墨卡托投影的,把 WGS84坐标系投影到正方形
     *
     */
    //与map一样,支持更详细的设置resolutions,fullExtent等
    const spatialReference = { projection: "EPSG:3857" },
      // 精确位置 [1, 1, -20037508.3427890,-20037508.3427890]
      tileSystem = [1, -1, -20037508.34, 20037508.34],
      // 滤镜 grayscale(1%) sepia(10%) hue-rotate(26.3deg) invert(0%) contrast(131%) saturate(63%)
      cssFilter = "grayscale(30%) sepia(10%) brightness(80%)",
      // 添加瓦片纠偏
      targetCoordinate = new maptalks.Coordinate(0, 0),
      POINT0 = new maptalks.Point(0, 0),
      POINT1 = new maptalks.Point(0, 0);
    // 基础瓦片图层
    this.baseLayer[0] = new maptalks.TileLayer(
      "base",
      // HBmap_base_config(cssFilter, spatialReference, tileSystem)
      GAODEmap_base_config(cssFilter, spatialReference, tileSystem)
      // GAODEmap_satellite_base_config(cssFilter, spatialReference, tileSystem)
    ) as maptalks.TileLayer;
    // 基础瓦片卫星图层
    this.baseLayer[1] = new maptalks.TileLayer(
      "base",
      // HBmap_base_config(cssFilter, spatialReference, tileSystem),
      // GAODEmap_base_config(cssFilter, spatialReference, tileSystem),
      GAODEmap_satellite_base_config(cssFilter, spatialReference, tileSystem)
    );
    // 巡逻图层
    this.markerLayer = new maptalks.VectorLayer("patrol", null, {
      hitDetect: false,
      zIndex: 10,
      // enableAltitude: true, // enable altitude
      // altitudeProperty: "altitude",
    });
    // 历史动画轨迹图层
    this.trakLayer = new maptalks.VectorLayer("trak", null, {
      hitDetect: false,
      zIndex: 9,
    });
    // 调度图层
    this.dispatchLayer = new maptalks.VectorLayer("dispatch", null, {
      hitDetect: false,
      zIndex: 8,
    });
    // // 区域图层
    // this.areaLayer = new maptalks.VectorLayer("area", null, {
    //   hitDetect: false,
    //   zIndex: 3,
    // });
    // 网格图层
    this.gridLayer = new maptalks.VectorLayer("grid", null, {
      hitDetect: false,
      zIndex: 2,
    });
    // 初始化地图实例
    this.map = new maptalks.Map(renderer, {
      // 是否在地图上显示属性控件。如果为真,属性显示 maptalks 信息;
      // 如果对象,您可以指定位置或您的基本内容,以及两者;
      attribution: false,
      // 地图的初始中心
      center,
      // 缩放等级
      zoom: HBMap.InitialZoom,
      minZoom: 11.5,
      maxZoom: 19,
      // 地图的空间参考,默认使用 EPSG:3857 投影,分辨率由 google map/osm 使用
      spatialReference,
      // 鹰眼
      // overviewControl: true,
      // 标尺
      scaleControl: {
        position: "bottom-right",
        maxWidth: 100,
        metric: true, // metric 米 nautical 海里 imperial 英寸
        imperial: false,
      },
      // 是否允许地图通过双击事件缩放
      doubleClickZoom: false,
      // 默认为真。如果为 true,则可以通过右键单击或 ctrl + 左键单击来拖动地
      // 图行旋转
      dragRotate: false,
      // 默认为真。如果为 true,则可以通过右键单击或 ctrl + 左键单击将地图拖动
      // 到俯仰
      dragPitch: false,
      // 如果为 true,地图将被拖动到同时俯仰和旋转
      dragRotatePitch: false,
      // 基础瓦片层
      baseLayer: this.baseLayer[0],
      // 最初将添加到地图的图层
      layers: [
        this.markerLayer,
        this.trakLayer,
        this.dispatchLayer,
        this.gridLayer,
        // this.areaLayer,
      ],
    });
    // 默认为真。拖动或触摸结束时继续动画平移
    this.map.config("panAnimation", false);
    // 默认为真。当拖动或触摸旋转结束时继续动画旋转
    this.map.config("rotateAnimation", false);
    // 默认为真。是否启用此地图上光标样式的图层命中检测,禁用它以提高性能
    this.map.config("hitDetect", false);
    // this.map.setPitch(30);
    // this.map.setBearing(5);
    // this.map.setFov(1);
    // 赋值弹窗回调函数
    this.infoWindowCallback = infoWindowCallback;
    this.changeModeCallback = changeModeCallback;
  }
  /** 根据carCode获取当前点位坐标 */
  getCoordinatesByCarCode(carCode: string) {
    const marker = this.carsMap.get(carCode);
    // console.log("getCoordinatesByCarCode", marker);
    if (marker) {
      return marker.carGeo;
    }
    return null;
  }
  /** 切换地图为卫星图 */
  changeBaseLayer(type: string) {
    switch (type) {
      case "base":
        this.map.setBaseLayer(this.baseLayer[0]);
        break;
      case "satellite":
        this.map.setBaseLayer(this.baseLayer[1]);
        break;
      default:
        break;
    }
  }
  /** 选择点位坐标 */
  setDispatchMarkerCoordinateMode(
    flag: boolean | undefined
  ): boolean | undefined {
    console.log("setDispatchMarkerCoordinateMode");
    if (typeof flag !== "undefined") {
      this.coordinateLocationMode = flag;
      return undefined;
    }
    this.coordinateLocationMode = !this.coordinateLocationMode;
    if (this.coordinateLocationMode) {
      // 绑定地图右键点击事件
      this.map.once("click", this.contextmenuEvent);
      console.log("contextmenu");
    } else {
      this.map.off("click", this.contextmenuEvent);
    }
    return this.coordinateLocationMode;
  }
  /** 右击时间回调 */
  contextmenuEvent({ coordinate }: any) {
    // console.log("setDispatchMarkerCoordinateMode", self.coordinateLocationMode);
    const dispatchId = utils.getUUID(),
      DispatchMarker = { dispatchId: dispatchId, coordinate, marker: null };
    // 创建调度点位
    if (self.coordinateLocationMode) {
      if (self.changeModeCallback) {
        // 判断是否为 undefined undefined代表主动回复不打点默认状态
        if (
          typeof self.changeModeCallback({
            dispatchId,
            coordinate,
          }) !== "undefined"
        ) {
          self.setDispatchMarkerCoordinateLocation(DispatchMarker);
        }
      }
    }
  }
  /** 回显调度点位 */
  setDispatchMarker(
    dispatchId: string,
    coordinate: Coordinate
  ): DispatchMarker {
    const DispatchMarker = { dispatchId, coordinate, marker: null };
    this.setDispatchMarkerCoordinateLocation(DispatchMarker);
    return DispatchMarker;
  }
  /** 新建调度点位 */
  setDispatchMarkerCoordinateLocation(dispatchData: MarkerLocation) {
    const dispatchMarker = self.DispatchMarkerMap.get(dispatchData.dispatchId);
    // console.log(
    //   "setDispatchMarkerCoordinateLocation",
    //   dispatchMarker,
    //   dispatchData
    // );
    if (!dispatchMarker) {
      // 新建点位
      const DispatchMarker = new maptalks.Marker(dispatchData.coordinate, {
          id: dispatchData.dispatchId,
          zIndex: 15,
          symbol: [
            {
              markerFile: dispatchSvg,
              markerHeight: 60,
              markerWidth: 60,
              markerOpacity: 1,
              markerVerticalAlignment: "middle",
            },
          ],
        }),
        option = {
          content: `<div class="icon">终</div><div>经度:${
            (dispatchData.coordinate && dispatchData.coordinate[0]) ||
            dispatchData.coordinate?.x
          } 纬度:${
            (dispatchData.coordinate && dispatchData.coordinate[1]) ||
            dispatchData.coordinate?.y
          }</div>`,
          className: "maptalks-tooltip-address",
          dy: -65,
        },
        // 创建自定义ui组件
        UI = this.createCustomUIComponent(),
        toolTip = new UI(dispatchData.coordinate, option);
      UI.mergeOptions(option);
      toolTip.addTo(this.map).show();
      DispatchMarker.addTo(this.dispatchLayer);
      self.DispatchMarkerMap.set(dispatchData.dispatchId, {
        ...dispatchData,
        toolTip,
        marker: DispatchMarker,
      });
    } else {
      // console.log("dispatchMarker.marker", dispatchMarker.marker);
      dispatchMarker.marker?.remove();
      dispatchMarker.toolTip?.remove();
      self.DispatchMarkerMap.delete(dispatchData.dispatchId);
    }
  }
  /** 更新车辆标记并更新最新方位角 */
  private updateDrawCar(
    {
      carCode,
      carTypeId,
      carMarker,
      infoWindowData,
      existCamera,
      existCarGeo,
      infoWindowVisiable,
    }: CarMarkerData,
    data: WSCarCoordinate | WSCarStatus,
    azimuth: number
  ): maptalks.Marker {
    // 更改点位
    if (carMarker) {
      if ("carGeo" in data) {
        data.carGeo && carMarker.setCoordinates(data.carGeo);
      }
    }
    // 判断是否要重绘消息弹窗
    if (typeof infoWindowVisiable === "boolean" && infoWindowVisiable) {
      // 绘制消息弹窗
      createInfoWindow({
        carCode,
        pointInfo: {
          ...infoWindowData,
          coordinate: (data as WSCarCoordinate).carGeo,
          existCamera,
          existCarGeo,
        },
        eventFunction: (type, carCode) => {
          if (this.infoWindowCallback) {
            const marker = this.carsMap.get(carCode as string);
            if (marker) {
              this.infoWindowCallback(type, marker);
            }
          }
        },
      });
    }
    // 更改点位信息
    // console.log(
    //   "markerFile",
    //   workStatus,
    //   utils.getCarStatusSvg(carTypeId, workStatus)
    // );
    const updateConfig: any = [
      {
        markerRotation: -azimuth,
      },
    ];
    if ("workStatus" in data) {
      updateConfig[0].markerFile = utils.getCarStatusSvg(
        carTypeId,
        data.workStatus as string
      );
      // console.log(
      //   222,
      //   data.workStatus,
      //   utils.getCarStatusSvg(carTypeId, data.workStatus)
      // );
    }
    carMarker!.updateSymbol(updateConfig);
    return carMarker!;
  }
  /** 批量更新车辆标记 */
  bathUpdateDrawCar(data: WSCarCoordinate | WSCarStatus) {
    // 存储全量车辆信息 间隔相同时间 请求全量数据
    if (Array.isArray(data)) {
      // 使用map更新单个点位
    } else if (data !== null && Object.keys(data).length) {
      const marker = this.carsMap.get(data.carCode);
      if (marker) {
        // 最新方位角(我也不知道为啥是取负 正数会显示镜像的方位)
        let newAzimuth: number = 0;
        // 包含点位 计算方位角
        if ("carGeo" in data) {
          newAzimuth = this.getAzimuth(
            marker.carGeo, // 旧点位
            data.carGeo as Coordinate // 新点位
          );
          // 状态变更 隐藏调度弹窗
        } else if ("workStatus" in data) {
          // 无坐标 取坐标角数组最后一位
        } else newAzimuth = marker.azimuth && marker.azimuth.slice(-1)[0];
        // console.log("azimuth Arr", data);
        this.carsMap.set(
          data.carCode,
          Object.assign(marker, {
            ...data,
            carMarker: this.updateDrawCar(marker, data, newAzimuth),
            azimuth: [...marker.azimuth, newAzimuth],
          })
        );
      }
    }
  }
  /** 创建新的ui组件 调度 */
  createCustomUIComponent() {
    class MyUI extends maptalks.ui.UIComponent {
      constructor(coordinate: Coordinate, options: BaseParameterData) {
        super(options);
        this._coordinate = new maptalks.Coordinate(coordinate);
      }
      // 创建dom元素
      buildOn() {
        const dom = document.createElement("div");
        dom.className = this.options.className;
        dom.innerHTML = this.options["content"];
        return dom;
      }
      getOffset() {
        const size = this.getSize();
        return new maptalks.Point(-size.width / 2, -size.height / 2);
      }
      getEvents() {
        return {
          zoomend: this._flash,
        };
      }
      onRemove() {
        if (this._flashTimeout) {
          clearTimeout(this._flashTimeout);
        }
      }
      _flash() {
        this.hide();
        this._flashTimeout = setTimeout(() => {
          this.show(this._coordinate);
        }, 200) as unknown as number;
      }
    }

    return MyUI;
  }
  /** 批量更新车辆状态 */
  bathUpdateMarkerStatus(data: WSCarStatus | WSCarStatus) {
    if ("workStatus" in data) {
      const { carCode, workStatus } = data;
      const marker = this.carsMap.get(carCode);
      if (marker) {
        // eslint-disable-next-line prefer-const
        let { carMarker, carNum, toolTip, showTip, carGeo } = marker;
        switch (workStatus) {
          case "DISPATCH":
            // console.log("DISPATCH 123");
            // eslint-disable-next-line no-case-declarations
            const option = {
                content: `<div>${carNum || "-"} 调度中</div>`,
                className: "maptalks-tooltip",
                dy: 45,
              },
              // 创建自定义ui组件
              UI = this.createCustomUIComponent(),
              ui = new UI(carGeo, option);
            UI.mergeOptions(option);
            ui.addTo(this.map).show();
            carMarker!.closeInfoWindow();
            toolTip = ui;
            showTip = true;
            break;
          default:
            if (toolTip) {
              toolTip.hide();
              toolTip = null;
              showTip = false;
            }
            break;
        }
        this.carsMap.set(
          carCode,
          Object.assign(marker, {
            carMarker: this.updateDrawCar(
              marker,
              data,
              marker.azimuth && marker.azimuth.slice(-1)[0]
            ),
            toolTip,
            showTip,
          })
        );
      }
    } else if ("status" in data) {
      const { carCode, status } = data;
      const marker = this.carsMap.get(carCode);
      console.log("ENABLED DISABLED", marker);
      if (marker) {
        if (status == "ENABLED") {
          // 关闭或展示
          marker.carMarker?.show();
          // 显示轨迹
          marker.line?.show();
          this.carsMap.set(
            carCode,
            Object.assign(marker, {
              show: true,
              enabled: true,
            })
          );
        } else {
          // 关闭或展示
          marker.carMarker?.hide();
          // 显示轨迹
          marker.line?.hide();
          this.carsMap.set(
            carCode,
            Object.assign(marker, {
              show: false,
              enabled: false,
            })
          );
        }
      }
    }
  }
  /** 绘制历史动画轨迹 */
  drawTrakLine(
    { carCode, carGeo }: WSCarCoordinate,
    { shadowColor, lineColor }: LineColor = {
      shadowColor: "#FFA300",
      lineColor: "#FFA300",
    }
  ): maptalks.LineString | null {
    const marker = this.carsMap.get(carCode);
    // console.log("drawTrakLine", marker, carCode);
    if (marker) {
      const line = new maptalks.LineString(
        (carGeo as Coordinate[]).map((item) => item),
        {
          zIndex: 9,
          symbol: {
            shadowColor,
            shadowBlur: 14,
            lineColor,
            lineWidth: 8,
            lineDasharray: [0, 0],
          },
        }
      );
      line.addTo(this.trakLayer);
      this.carsMap.set(carCode, {
        ...marker,
        line,
      });
      return line;
    }
    return null;
  }
  /** 绘制车辆历史标记点 */
  drawHistoryCar(carCode: string, carGeo: Coordinate) {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      // 创建一个Marker对象
      const carMarker = new maptalks.Marker(carGeo, {
        symbol: [
          {
            markerFile: utils.getCarStatusSvg(marker.carTypeId, "OFFLINE"),
            markerHeight: 60,
            markerWidth: 60,
            markerOpacity: 1,
            markerVerticalAlignment: "middle",
          },
        ],
      }).addTo(this.trakLayer);
      this.carsMap.set(carCode, {
        ...marker,
        carMarker,
      });
    }
  }
  /** 插入车辆点线动画 */
  playHistoryAnimateVideo(carCode: string, route: any): null | RoutePlayer {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      const player = new RoutePlayer(route, this.map, {
        maxTrailLine: 10,
      });
      this.carsMap.set(carCode, {
        ...marker,
        carHistoryVideo: player,
      });
      return player;
    }
    return null;
  }
  /** 绘制车其他标记点 */
  drawOtherHistoryMarkers(carGeos: Coordinate[]) {
    for (let i = 0; i < carGeos.length; i++) {
      let markerFile: any = "ONLINE";
      // 开始
      if (i === 0) {
        markerFile = utils.getCarStatusSvg(-1, "START");
        // 结束
      } else if (i === carGeos.length - 1) {
        markerFile = utils.getCarStatusSvg(-1, "END");
        // 停留
      } else {
        markerFile = utils.getCarStatusSvg(-1, "PAUSE");
      }
      const car = new maptalks.Marker(carGeos[i], {
        id: i,
        zIndex: 9,
        symbol:
          i === 0 || i === carGeos.length - 1
            ? {
                markerFile,
                markerHeight: 40,
                markerWidth: 40,
                markerOpacity: 1,
                markerVerticalAlignment: "top",
                markerDx: 3,
                markerDy: -10,
              }
            : {
                markerFile,
                markerHeight: 80,
                markerWidth: 80,
                markerOpacity: 0.9,
                markerVerticalAlignment: "middle",
                markerDx: -12,
                markerDy: -10,
              },
      });
      car.addTo(this.trakLayer);
    }
  }
  /** 绘制车辆历史路线 */
  // drawHistoryCarPath({
  //   carCode,
  //   carGeos = [],
  //   lineColor = "#000",
  // }: AnimateiHstoryCarPath) {
  //   const marker = this.carsMap.get(carCode);
  //   if (marker) {
  //     // 创建一个Path对象
  //     const linePath = new maptalks.Path(
  //       carGeos.length ? carGeos : marker.line?.getCoordinates(),
  //       {
  //         symbol: {
  //           lineColor,
  //           lineWidth: 2,
  //         },
  //       }
  //     ).addTo(this.trakLayer);
  //     this.carsMap.set(carCode, {
  //       ...marker,
  //       linePath,
  //     });
  //   }
  // }
  /** 执行车辆历史路线动画 */
  // takeHistoryCarAnimate(carCode: string, duration: number) {
  //   const marker = this.carsMap.get(carCode);
  //   if (marker) {
  //     // 执行Marker的animate动画方法
  //     marker.carMarker!.animate({
  //       path: marker.linePath, // 设置路径为刚刚创建的Path对象
  //       duration, // 动画持续时间为5000毫秒
  //       easing: "linear", // 动画缓动函数为线性
  //       repeat: false, // 动画循环执行
  //       autoRotate: true, // 自动旋转方向
  //     });
  //   }
  // }
  /** 车辆展示或关闭弹框 */

  /**
   * @description:
   * @param carCode {string}  :车辆标识
   * @param carMarker {maptalks}  :车辆点位
   * @response: DISABLED 启用禁用状态
   *            DISCOORDINATE 该车不存在或无点位
   * @return {*}
   */
  async showCarInfoWindow(
    carCode: string,
    carMarker: maptalks.Marker | null
  ): Promise<boolean | string> {
    const marker = this.carsMap.get(carCode);
    console.log("能不能获取到", this.carsMap, carCode);
    if (marker) {
      // 如果当前为打开自定义组件ui时终止
      if (marker.showTip) return true;
      // 如果为跟踪点位 添加到跟踪数组中 存在着不添加
      if (marker.follow) {
        !this.followCarArr.includes(marker.carCode) &&
          this.followCarArr.push(marker.carCode);
        return true;
      }
      // 判断车辆启用禁用状态
      if (!marker.enabled) return "DISABLED";
      // 创建点位弹窗
      (carMarker || marker.carMarker!).setInfoWindow({
        // 如果您不希望地图进行平移动画以适应打开的窗口,请将其设置为 false。
        autoPan: true,
        // 自动打开所有者事件的信息窗口,例如“单击”将通过单击或右键单击窗口所有者打开信息窗口。
        autoOpenOn: null,
        // UI是否为全局单个UI,设置为true则同一时间只显示一个UI
        single: false,
        // 如果您想要自定义信息窗口、自定义 html 代码或将 HTMLElement 设置为内容,请将其设置为 true。
        custom: true,
        // 信息窗口的内容。
        content: "",
        visible: true,
        dx: -130,
        dy: -160,
        animation: "fade",
      });
      // console.log("marker", marker);
      // 获取当前点位上的弹窗对象
      const infoW = (carMarker || marker.carMarker!).getInfoWindow();
      // 写入弹窗内容
      this.infoWindowContent(infoW, marker.carCode);
      // 如果没有当前点击marker值 赋值
      if (!this.currentCarMarker) {
        (carMarker || marker.carMarker!).openInfoWindow();
        this.currentCarMarker = marker;
        // 获取弹窗展示的信息
        let info = await infoWindowData(
          carCode,
          this.getCoordinatesByCarCode(carCode)
        );
        // console.log("1231231213 infoWindowData",marker)
        info = {
          ...info,
          existCamera: marker?.existCamera,
          existCarGeo: marker?.existCarGeo,
        };
        console.log("单机弹窗", info);
        // 放入对应点位对象
        this.setInfoWindowData(carCode, info);
        // 绘制消息弹窗
        createInfoWindow({
          carCode,
          pointInfo: info,
          eventFunction: (type, carCode) => {
            if (this.infoWindowCallback) {
              const marker = this.carsMap.get(carCode as string);
              if (marker) {
                this.infoWindowCallback(type, marker);
              }
            }
          },
        });
        this.updateInfoWindowVisiable(carCode, true);
        // 定位车辆
        this.map.animateTo(
          {
            center: marker.carGeo,
            zoom: HBMap.InitialCarZoom,
          },
          {
            duration: 2 * 1000,
          }
        );
        // 相同代表点击同一个marker
      } else if (this.currentCarMarker.carCode === marker.carCode) {
        // 更新点位消息弹窗状态
        this.updateInfoWindowVisiable(carCode, false);
        // 再删除弹窗
        setTimeout(
          () => (carMarker || marker.carMarker!).removeInfoWindow(),
          0
        );
        this.currentCarMarker = null;
        // 定位车辆
        this.map.animateTo(
          {
            center: HBMap.InitialCoordinate,
            zoom: HBMap.InitialZoom,
          },
          {
            duration: 2 * 1000,
          }
        );
        // 否则是关闭一个已经打开的弹窗 打开一个新marker弹窗
      } else {
        // 其中 先判断上一个点位对象是否在跟踪数组中 不存在则关闭上一个弹窗
        if (!this.followCarArr.includes(this.currentCarMarker.carCode)) {
          // console.log(1231231123);
          // 更新点位消息弹窗状态
          this.updateInfoWindowVisiable(this.currentCarMarker?.carCode, false);
          this.currentCarMarker?.carMarker?.removeInfoWindow();
        }
        // 更新点位消息弹窗状态
        // setTimeout(async () => {
        (carMarker || marker.carMarker!).openInfoWindow();
        this.currentCarMarker = marker;
        // 获取弹窗展示的信息
        let info = await infoWindowData(
          carCode,
          this.getCoordinatesByCarCode(carCode)
        );
        info = {
          ...info,
          existCamera: marker?.existCamera,
          existCarGeo: marker?.existCarGeo,
        };
        // 放入对应点位对象
        this.setInfoWindowData(carCode, info);
        // 绘制消息弹窗
        createInfoWindow({
          carCode,
          pointInfo: info,
          eventFunction: (type, carCode) => {
            if (this.infoWindowCallback) {
              const marker = this.carsMap.get(carCode as string);
              if (marker) {
                this.infoWindowCallback(type, marker);
              }
            }
          },
        });
        this.updateInfoWindowVisiable(carCode, true);
        // 定位车辆
        this.map.animateTo(
          {
            center: marker.carGeo,
            zoom: HBMap.InitialCarZoom,
          },
          {
            duration: 2 * 1000,
          }
        );
        // }, 1000);
      }
      return true;
    } else return "DISCOORDINATE";
  }
  /** 绘制车辆标记 */
  private drawCar({
    carCode,
    carTypeId,
    carGeo,
    workStatus,
    azimuth,
  }: CarMarkerData): maptalks.Marker {
    // console.log(
    //   "drawCar",
    //   workStatus,
    //   utils.getCarStatusSvg(carTypeId, workStatus || "OFFLINE")
    // );
    const that = this,
      car = new maptalks.Marker(carGeo, {
        id: carCode,
        zIndex: 15,
        symbol: [
          {
            markerFile: utils.getCarStatusSvg(
              carTypeId,
              workStatus || "OFFLINE"
            ),
            markerHeight: 60,
            markerWidth: 60,
            markerOpacity: 1,
            markerVerticalAlignment: "middle",
            markerRotation: azimuth.concat().pop(),
          },
          // {
          //   markerHeight: 60,
          //   markerWidth: 60,
          //   markerFill: "rgba(255, 255, 255, 0)",
          //   markerType: "ellipse",
          //   markerLineWidth: 0,
          // },
        ],
        properties: {
          altitude: 400,
        },
      });
    car.addTo(this.markerLayer);
    car.on("click", async function (e) {
      // 不为跟踪点位 不同点位点击需要进行弹窗重绘
      that.showCarInfoWindow(e.target._id, car);
    });
    // 显示车牌
    // car.on("mouseenter", async function (e) {
    //   const marker = that.carsMap.get(e.target._id);
    //   if (marker) {
    //     if (marker.toolTip2) {
    //       marker.toolTip2.show(new maptalks.Coordinate(marker.carGeo));
    //     } else {
    //       const toolTip2 = new maptalks.ui.ToolTip(`${marker.carNum || "-"}`, {
    //         width: 70,
    //         height: 30,
    //         showTimeout: 60 * 1000,
    //         animationDuration: 2000,
    //         animation: "scale | fade",
    //         // autoPan: true, 不能加这个煞笔属性 艹卡了我一下午
    //         // 自动打开所有者事件的信息窗口,例如“单击”将通过单击或右键单击窗口所有者打开信息窗口。
    //         // cssName: "marker-tooltip-car-num",
    //         // UI是否为全局单个UI,设置为true则同一时间只显示一个UI
    //         single: false,
    //         dx: -35,
    //         dy: 35,
    //       });
    //       toolTip2.setStyle("marker-tooltip-car-num");
    //       toolTip2.addTo(marker.carMarker!);
    //       toolTip2.show(new maptalks.Coordinate(marker.carGeo));
    //       that.carsMap.set(e.target._id, {
    //         ...marker,
    //         toolTip2,
    //       });
    //     }
    //   }
    // });
    // // 隐藏车牌
    // car.on("mouseout", async function (e) {
    //   const marker = that.carsMap.get(carCode);
    //   if (marker) {
    //     marker.toolTip2!.hide();
    //   }
    // });

    return car;
  }
  /** 批量绘制车辆标记 */
  bathDrawCar(carsArr: Array<CarMarkerData>): void {
    // 存储全量车辆信息
    console.log("bathDrawCar", carsArr);
    for (let i = 0; i < carsArr.length; i++) {
      const carData = {
        ...carsArr[i],
      };
      console.log("carData", carData);
      carsArr[i] = Object.assign(carData, {
        carMarker: this.drawCar(carData),
      });
      // 隐藏禁用的车辆
      if (!carsArr[i].enabled) carsArr[i].carMarker?.hide();
      this.carsMap.set(carsArr[i].carCode, carData);
      // console.log("!carsArr[i].enabled", !carsArr[i].enabled);
      // console.log("bathDrawCar carsArr[i]", carsArr[i], this.carsMap);
    }
    // this.carsArr = carsArr;
  }
  /** 添加指定carCode车辆信息 */
  addNewCarMapObject(car: CarMarkerData) {
    const { carCode } = car;
    this.carsMap.set(carCode, car);
  }
  /** 点位消息窗口是否打开 */
  updateInfoWindowVisiable(carCode: string, visiable: boolean) {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      this.carsMap.set(carCode, {
        ...marker,
        infoWindowVisiable: visiable,
      });
    }
  }
  /** 点位赋值消息窗口信息 */
  setInfoWindowData(carCode: string, infoWindowData: InfoWindowData) {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      this.carsMap.set(carCode, {
        ...marker,
        infoWindowData,
      });
    }
  }
  /** 重绘消息窗口 */
  infoWindowContent(ifoWindow: maptalks.ui.InfoWindow, carCode: string) {
    return (
      ifoWindow &&
      ifoWindow.setContent(`<div id="info-content-${carCode}"></div>`)
    );
  }
  /** 跟踪车辆消息窗口 */
  drawTrackCarinfoWindow(carCode: string, carInfo: any) {
    const marker = this.carsMap.get(carCode),
      that = this;
    if (marker) {
      marker?.carMarker?.setInfoWindow({
        // 如果您不希望地图进行平移动画以适应打开的窗口,请将其设置为 false。
        autoPan: false,
        zIndex: 16,
        // 自动打开所有者事件的信息窗口,例如“单击”将通过单击或右键单击窗口所有者打开信息窗口。
        autoOpenOn: null,
        // UI是否为全局单个UI,设置为true则同一时间只显示一个UI
        single: false,
        // 如果您想要自定义信息窗口、自定义 html 代码或将 HTMLElement 设置为内容,请将其设置为 true。
        custom: true,
        // 信息窗口的内容。
        content: "",
        dx: -130,
        dy: -160,
        animation: "fade",
      });
      // 获取当前点位上的弹窗对象
      // 写入弹窗内容
      that.infoWindowContent(marker?.carMarker?.getInfoWindow()!, carCode);
      marker?.carMarker?.openInfoWindow();
      // console.log("carInfo carInfo", carInfo);
      createInfoWindow({
        carCode,
        pointInfo: {
          ...carInfo,
          existCamera: marker?.existCamera,
          existCarGeo: marker?.existCarGeo,
        },
        eventFunction: (type, carCode) => {
          if (this.infoWindowCallback) {
            const marker = this.carsMap.get(carCode as string);
            if (marker) {
              this.infoWindowCallback(type, marker);
            }
          }
        },
      });
      // 更新点位消息弹窗状态
      that.updateInfoWindowVisiable(carCode, true);
    }
  }
  /** 初始化跟踪车辆轨迹点位数组 */
  initTrckCarCoordinateArr(
    carCode: string,
    coordinates: Coordinate[]
  ): Coordinate[] | null {
    const marker = this.carsMap.get(carCode as string);
    if (marker) {
      marker.trakCollection = coordinates;
      this.carsMap.set(carCode, marker);
      return coordinates;
    }
    return null;
  }
  /** 查找跟踪车辆轨迹点位数组 */
  getTrckCarCoordinateArr(carCode: string): Coordinate[] | [] {
    const marker = this.carsMap.get(carCode);
    // console.log("getTrckCarCoordinateArr", marker, this.carsMap);
    return marker ? marker.trakCollection : [];
  }
  /** 更新跟踪车辆轨迹点位数组 */
  updateTrckCarCoordinateArr({
    carCode,
    carGeo,
  }: WSCarCoordinate): Coordinate[] | null {
    const marker = this.carsMap.get(carCode as string);
    if (marker) {
      marker.trakCollection.push(carGeo as Coordinate);
      this.carsMap.set(carCode as string, marker);
      return marker.trakCollection;
    }
    return null;
  }
  /** 混合更新跟踪车辆轨迹点位数组 */
  updateMixTrckCarCoordinateArr({
    carCode,
    carGeo,
    uploadTime,
  }: WSCarCoordinate): Coordinate[] | null {
    const marker = this.carsMap.get(carCode);
    // console.log(
    //   ` updateMixTrckCarCoordinateArr`,
    //   carCode,
    //   uploadTime,
    //   this.carsMap,
    //   marker
    // );
    if (marker) {
      if (
        Array.isArray((carGeo as Coordinate[])[0]) &&
        Array.isArray(uploadTime as string[])
      ) {
        const trakCollection = marker.trakCollection.concat(
          carGeo as Coordinate[]
        );
        // console.log("marker.uploadTime", marker.uploadTime);
        const uploadTimeTemp = (
          Array.isArray(marker.uploadTime)
            ? marker.uploadTime
            : [marker.uploadTime]
        ).concat(uploadTime as string[]);
        this.carsMap.set(carCode, {
          ...marker,
          trakCollection,
          uploadTime: uploadTimeTemp,
        });
        return trakCollection;
      } else {
        const trakCollection = [
          ...marker.trakCollection,
          carGeo,
        ] as Coordinate[];
        let uploadTimeArr = [];
        if (Array.isArray(marker.uploadTime)) {
          uploadTimeArr = [...marker.uploadTime, uploadTime] as string[];
        } else uploadTimeArr.push(uploadTime);
        this.carsMap.set(carCode, {
          ...marker,
          trakCollection,
          uploadTime: uploadTimeArr as string[],
        });
        // console.log("updateMixTrckCarCoordinateArr", this.carsMap.get(carCode));
        return trakCollection;
      }
    }
    return null;
  }
  /** 清空跟踪车辆轨迹点位数组 */
  clearTrckCarCoordinateArr(carCode: string) {
    const marker = this.carsMap.get(carCode as string);
    if (marker) {
      this.carsMap.set(carCode as string, {
        ...marker,
        trakCollection: [],
      });
    }
  }
  /** 更新轨迹 */
  updateTrakLine({ carCode, carGeo }: WSCarCoordinate): void {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      const { line } = marker;
      line?.setCoordinates(carGeo as Coordinate[]);
      // console.log("updateTrakLine carGeo", carGeo);
    }
  }
  /** 清除轨迹 */
  clearTrakLine(carCode: string): void {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      const { line } = marker;
      line?.remove();

      this.carsMap.set(carCode, { ...marker, line: null });
    }
  }
  /** 聚焦 */
  focusOnMarker(points: Coordinate, duration: number, focus: boolean = false) {
    // console.log("focusOnMarker", this.carFocus, points);
    if (!focus) return;
    this.map.animateTo(
      {
        center: points,
        zoom: this.map.getZoom(),
      },
      {
        duration,
      }
    );
  }
  /** 获取当前跟踪车辆信息 */
  getMapObjectById(carCode: string): CarMarkerData | null {
    return this.carsMap.get(carCode) ?? null;
  }
  /** 已知两点计算角标 */
  // getAzimuth(prvCoordinate: Coordinate, curCoordinate: Coordinate): number {
  //   // console.log("getAzimuth", prvCoordinate, curCoordinate);
  //   let azimuth = 0;
  //   const [lat1, lon1] = prvCoordinate,
  //     [lat2, lon2] = curCoordinate,
  //     dlat = lat2 - lat1,
  //     dlon = lon2 - lon1;
  //   if (dlon === 0) {
  //     azimuth = dlat > 0 ? 90 : -90;
  //   } else if (dlat === 0) {
  //     azimuth = dlon > 0 ? 0 : 270;
  //   } else {
  //     azimuth = (Math.atan(dlat / dlon) * 180) / Math.PI;
  //     if (dlon < 0) {
  //       azimuth += 180;
  //     } else if (dlon >= 0 && dlat < 0) {
  //       azimuth += 360;
  //     }
  //   }
  //   return azimuth;
  // }
  getAzimuth([lon1, lat1]: Coordinate, [lon2, lat2]: Coordinate) {
    const lon1_rad = (lon1 * Math.PI) / 180;
    const lat1_rad = (lat1 * Math.PI) / 180;
    const lon2_rad = (lon2 * Math.PI) / 180;
    const lat2_rad = (lat2 * Math.PI) / 180;
    const tan_y = Math.tan(lat2_rad - lat1_rad);
    const tan_x =
      Math.sin(lon2_rad - lon1_rad) * Math.cos(lat1_rad) -
      Math.cos(lon2_rad - lon1_rad) *
        Math.sin(lat1_rad) *
        Math.cos(lat2_rad - lat1_rad);
    let azimuth = Math.atan2(
      Math.sin(lon2_rad - lon1_rad) * Math.cos(lat2_rad),
      Math.cos(lat1_rad) * Math.sin(lat2_rad) -
        Math.sin(lat1_rad) * Math.cos(lat2_rad) * Math.cos(lon2_rad - lon1_rad)
    );
    azimuth = (azimuth * 180) / Math.PI;
    return azimuth;
  }
  /** 关闭跟踪车辆弹窗 */
  closeTrackCarinfoWindow(carCode: string) {
    const marker = this.carsMap.get(carCode);
    // // console.log("closeTrackCarinfoWindow", marker);
    if (marker) {
      const infoW = marker?.carMarker?.getInfoWindow();
      marker?.carMarker?.closeInfoWindow();
      // 在删除弹窗dom
      setTimeout(() => infoW?.remove(), 0);
    }
  }

  /** 设置车辆跟踪状态 */
  updateCarMarkerFollowStatus(carCode: string): boolean {
    if (
      this.followCarArr.length >= HBMap.infoWindowNum &&
      !this.followCarArr.includes(carCode)
    )
      return false;
    const marker = this.carsMap.get(carCode);
    if (marker) {
      this.carsMap.set(carCode, {
        ...marker,
        follow: !marker.follow,
      });
      const newMarker = this.carsMap.get(carCode)!;
      // 变更跟随模式时 更新当前点击对象
      this.currentCarMarker = newMarker;
      // 更新最新跟踪数组
      if (newMarker.follow && !this.followCarArr.includes(carCode))
        this.followCarArr.push(carCode);
      else
        this.followCarArr.splice(
          this.followCarArr.findIndex((f) => f === carCode),
          1
        );
      // 如果当前跟踪车辆大约两台 取消跟随某辆车状态
      // this.carFocus = this.followCarArr.length < 2;
      // // console.log("this.carsMap.get(carCode)", newMarker);
    }
    return true;
  }
  /** 改变车辆map属性变化 */
  setCarMapProperty(carCode: string, property: any): void {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      this.carsMap.set(carCode, Object.assign(marker, property));
    }
  }
  /** 改变车辆marker显隐 */
  async setCarMarkerVisiable(carTypeArr: number[]) {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    for (const [key, value] of this.carsMap.entries()) {
      let inArr = false;
      const marker = this.carsMap.get(value.carCode);
      carTypeArr.forEach((type) => type === value.carTypeId && (inArr = true));
      if (inArr) {
        if (marker) {
          // 关闭或展示
          marker.carMarker?.show();
          // 显示轨迹
          marker.line?.show();
          // 如果为跟踪状态 需要重新绑定
          if (marker.follow) {
            // 获取当前点位上的弹窗对象
            const infoW = marker.carMarker?.getInfoWindow(),
              carCode = marker.carCode;
            if (infoW) {
              marker.carMarker?.openInfoWindow();
              // // 写入弹窗内容
              this.infoWindowContent(infoW, carCode);
              // 如果没有当前点击marker值 赋值
              marker.carMarker?.openInfoWindow();
              this.currentCarMarker = marker;
              // 获取弹窗展示的信息
              let info = await infoWindowData(
                carCode,
                this.getCoordinatesByCarCode(carCode)
              );
              info = {
                ...info,
                existCamera: marker?.existCamera,
                existCarGeo: marker?.existCarGeo,
              };
              // 放入对应点位对象
              this.setInfoWindowData(carCode, info);
              // console.log(11111);
              // 绘制消息弹窗
              createInfoWindow({
                carCode,
                pointInfo: info,
                eventFunction: (type) => {
                  if (this.infoWindowCallback) {
                    if (marker) {
                      this.infoWindowCallback(type, marker);
                    }
                  }
                },
              });
            }
          }
          this.carsMap.set(
            value.carCode,
            Object.assign(marker, {
              show: true,
            })
          );
        }
      } else {
        if (marker) {
          // 关闭或展示
          marker.carMarker?.hide();
          // 隐藏轨迹
          marker.line?.hide();
          this.carsMap.set(
            value.carCode,
            Object.assign(marker, {
              show: false,
            })
          );
        }
      }
    }
  }
  /** 根据carCode获取点位 */
  getCoordinateByCarCode(carCode: string) {
    const marker = this.carsMap.get(carCode);
    return marker ? marker.carGeo : [];
  }
  /** 清空carCode轨迹数组 */
  clearTrakCollectionByCarCode(carCode: string) {
    const marker = this.carsMap.get(carCode);
    if (marker) {
      this.carsMap.set(carCode, {
        ...marker,
        trakCollection: [],
      });
    }
  }
  /** 根据carCode获取轨迹数组 */
  getTrakCollectionByCarCode(carCode: string): Coordinate[] | Coordinate {
    const marker = this.carsMap.get(carCode);
    // console.log("getTrakCollectionByCarCode", marker);
    if (marker) {
      return marker.trakCollection.length
        ? marker.trakCollection || []
        : marker.carGeo;
    }
    return [];
  }

  /** 添加独立tooltip */
  addToolTip(polygon: maptalks.Polygon, name: string) {
    const toolTip = new maptalks.ui.ToolTip(name, {
      width: 100,
      height: 30,
      animation: "scale | fade",
      // autoPan: true,
      // 自动打开所有者事件的信息窗口,例如“单击”将通过单击或右键单击窗口所有者打开信息窗口。
      // cssName: "marker-tooltip-car-num",
      // UI是否为全局单个UI,设置为true则同一时间只显示一个UI
      single: false,
      dx: -35,
      dy: -55,
    });
    toolTip.setStyle("marker-tooltip-grid");
    toolTip.addTo(polygon);
    return toolTip;
  }

  /**
   * 地图上划区域
   * @param {Array} points
   * @param {Object} config 用来设置区域样式
   * @param {String} eventType 时间类型 格式 'mousedown mouseup click dblclick contextmenu touchstart touchend mouseenter mouseout'
   * @param {Function} onEvent 时间总处理方法
   */
  // points: Coordinate[] = [],
  // config: BaseParameterData,
  // eventType: string | null,
  // onEvent: maptalks.EvenableHandlerFun | null
  drawArea({ points = [], config = {}, onEvent = null }: AreaData) {
    // const areaArr: maptalks.Polygon[] = [];
    let isFocus: boolean = false;
    points.forEach((point) => {
      const area = new maptalks.Polygon(point.geo as Coordinate[], {
          ...config,
          id: point.id,
        }),
        toolTip = this.addToolTip(area, point.name);
      area
        .addTo(this.areaLayer!)
        .on("click", (e) => {
          if (onEvent) {
            onEvent(e, point, "click");
          }
        })
        .on("dblclick", (e) => {
          isFocus = !isFocus;
          if (isFocus) {
            this.map?.fitExtent(area.getExtent(), 1);
          } else {
            this.map.setZoom(HBMap.InitialZoom);
          }
          if (onEvent) {
            onEvent(e, point, "dblclick");
          }
        })
        .on("mouseenter", (e) => {
          console.log("mouseenter", e);
          toolTip.show();
          area.updateSymbol({
            polygonOpacity: 0.4,
          });
        })
        .on("mouseout", (e) => {
          console.log("mouseenter", e);
          toolTip.hide();
          area.updateSymbol({
            polygonOpacity: 0.1,
          });
        });

      // areaArr.push(area);
    });
  }
  /**
   * 地图上划区域
   * @param {Array} points
   * @param {Object} config 用来设置区域border样式
   * @param {String} eventType 时间类型 格式 'mousedown mouseup click dblclick contextmenu touchstart touchend mouseenter mouseout'
   * @param {Function} onEvent 时间总处理方法
   */
  drawAreaBorder({
    points = [],
    config = {},
    eventType = null,
    onEvent = null,
  }: AreaData): maptalks.LineString[] {
    const lineArr: maptalks.LineString[] = [];
    console.log("points", points);
    points.forEach((point) => {
      // console.log(123123, point);
      lineArr.push(
        new maptalks.LineString(point.geo as Coordinate[], {
          ...config,
          id: `line-${point.id}`,
          properties: {
            altitude: new Array(point.geo.length).fill(
              config?.properties?.altitude || 0
            ),
          },
        }).on(eventType ? eventType : "click", (e) => {
          console.log("drawAreaBorder", lineArr);
          if (onEvent) {
            onEvent(e, point);
          }
        })
      );
    });
    console.log("this.areaLayer this.areaLayer", this.areaLayer);
    if (!this.areaLayer) {
      this.areaLayer = new maptalks.VectorLayer("area", lineArr, {
        enableAltitude: true,
        drawAltitude: {
          polygonFill: "#489bfb",
          polygonOpacity: 0.3,
          lineWidth: 0,
        },
        zindex: 3,
      });
      this.areaLayer.addTo(this.map);
    } else {
      this.areaLayer.addGeometry(lineArr);
    }
    return lineArr;
  }

  /** 删除当前添加的下级网格 */
  removeVectorLayerGeometrys(
    removeGeometry: maptalks.Geometry | maptalks.Geometry[]
  ) {
    this.areaLayer!.removeGeometry(removeGeometry);
  }

  /** 清除所有网格 */
  clearAllAreas() {
    this.areaLayer?.clear();
    this.map?.removeLayer(this.areaLayer!);
    this.areaLayer = null;
  }
  // ------------------------------------------------------------------------------------

  /** 清除交互后 ImageData 缓存 */
  clearMapCache() {
    setTimeout(() => {
      const layers = this.map.getLayers();
      layers.forEach((layer) => {
        layer.getRenderer().clearImageData();
      });
    }, 100);
  }
  /** 设置车辆标记位置 */
  moveCar(point: number[]) {
    this.car.setCoordinates(point);
  }
  /** 地图自适应展示图形 */
  fitExtent(geo: Extentable, zoomOffset = 0) {
    this.map.fitExtent(geo.getExtent(), zoomOffset);
  }
}
© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏

评论 (0)

取消