多地图(百度、高德、腾讯地图)API 组件封装

348 阅读2分钟

实现方法:在封装多地图(百度地图、高德地图、腾讯地图)组件时,可以定义一个接口(interface)或一个抽象类(abstract),然后为每个地图API实现这个接口或抽象类,这样我的应用程序就可以通过调用统一的接口与不同的地图API进行交互,而不需要关心底层的逻辑实现的具体细节

// 1 引入
import BMap from 'BMap'; // 百度
import AMap from 'AMap'; // 高德
import * as qq from '@qq/maps' // 腾讯

// 2 定义类型
// 2.1 位置类型
type Position = { // 定义类型
  lng: number, // 经度
  lat: number // 维度
}

// interface 接口 
// 定义百度、高德、腾讯地图API需要实现的方法 且必须实现
// 后期在定义一个工厂类 实现统一调用
// 2.1 百度
interface BaiduMarker extends BMap.Marker { }
interface BaiduMarkerOptions extends BMap.MarkerOptions {
  position: Position;
}
// 2.2 高德
interface GaodeMarker extends AMap.Marker { }
interface GaodeMarkerOptions extends AMap.MarkerOptions {
  position: Position;
}

// 泛型接口:e<TMarker, TMarkerOptions>允许在定义类型或函数时指定一个占位符类型,然后在使用时提供具体类型 目的:根据传入的类型参数动态地处理不同的地图API
interface MapService<TMarker, TMarkerOptions> {
  // 地图初始化
  init: (id: string, options?: any) => void;
  // 添加撒点
  addMarker: (position: Position, options?: TMarkerOptions) => TMarker;
  // 移除撒点
  removeMarker: (marker: TMarker) => void
}

// 百度地图API
class BaiduMapService implements MapService<BaiduMarker, BaiduMarkerOptions>{
  // 定义内部资源类型
  private map: BMap.Map
  // 初始化
  init(id: string, options?: any): void {
    this.map = new BMap.Map(id)
    if (options) {
      // 设置地图中心坐标+级别
      const point = new BMap.Point(options.center.lng, options.center.lat);
      this.map.centerAndZoom(point, options.zoom);
      // 其他设置...
    }
  }
  // 添加撒点
  addMarker(position: Position, options?: BaiduMarkerOptions): BaiduMarker {
    const marker = new BMap.Marker(new BMap.Point(position.lng, position.lat), options)
    this.map.addOverlay(marker)
    return marker
  }
  // 移除撒点
  removeMarker(marker: BaiduMarker): void {
    this.map.removeOverlay(marker)
  }
}

// 高德地图API
class GaodeMapService implements MapService<GaodeMarker, GaodeMarkerOptions>{
  private map: AMap.Map
  // 初始化
  init(id: string, options?: any): void {
    this.map = new AMap.Map(id, options)
  }
  // 添加撒点
  addMarker(position: Position, options?: GaodeMarkerOptions): GaodeMarker {
    const marker = new AMap.Marker({
      position: [position.lng, position.lat],
      ...options
    })
    this.map.add(marker)
    return marker
  }
  // 移除撒点
  removeMarker(marker: GaodeMarker): void {
    this.map.remove(marker)
  }
}

class TengxunMapService implements MapService<any, any> {
  private map: any; // 腾讯地图的实例类型可能不同  
  // 初始化
  init(id: string, options?: any): void {
    this.map = new qq.maps.Map(id, options);
  }
  // 添加撒点
  addMarker(position: Position, options?: any): any {
    const marker = new qq.maps.Marker({
      position: new qq.maps.LatLny(position.lat, position.lng),
      ...options
    })
    this.map.addOverlay(marker)
    return marker;
  }
  // 移除撒点
  removeMarker(marker: any): void {
    this.map.removeOverlay(marker)
  }
}

// 采用工厂类 调用实例
class MapServiceFactory {
  static createMapService<TMarker, TMarkerOptions>(type: string): MapService<TMarker, TMarkerOptions> {
    switch (type) {
      case 'baidu':
        return new BaiduMapService() as MapService<TMarker, TMarkerOptions>;
      case 'gaode':
        return new GaodeMapService() as MapService<TMarker, TMarkerOptions>;
      case 'tengxun':
        return new TengxunMapService() as MapService<TMarker, TMarkerOptions>;
      default:
        throw new Error('Unsupported map type')
    }
  }
}

// 使用
<div id='map-container' > </div>
const options = { /* 地图初始化选项 */ };
const mapService = MapServiceFactory.createMapService('baidu');
mapService.init('map-container', options)
const markers = [/* 标记点数据 */];
markers.forEach(item => {
  mapService.addMarker(item.position, item.options);
});