类名 document/support/mapbox/mapboxCustomUtil.js
function mapboxCustomCRS(mapboxgl, proj4) {
  class MapboxglCustomProjection extends mapboxgl.Projection {
    constructor(code, options) {
      super()
      const opts = options || {}
      const def = opts.def
      if (!def) {
        throw new Error('自定义参考系必须指定参数系信息def')
      }
      this._def = def
      // 验证proj4库是否存在
      if (!proj4) {
        throw new Error('proj4对象不存在,自定义投影必须引入proj4对象')
      }

      const isP4 = this._isProj4Obj(code)
      this._proj = isP4 ? code : this._projFromCodeDef(code, def)
    }

    /**
     * @description: 正投
     * @param {*} lnglat
     * @return {*}
     */
    project(lnglat) {
      let lng
      let lat
      if (Array.isArray(lnglat)) {
        lng = lnglat[0]
        lat = lnglat[1]
      } else {
        lng = lnglat.lng
        lat = lnglat.lat
      }
      return this._proj.forward([lng, lat])
    }

    /**
     * @description: 反投
     * @param {*} point
     * @return {*}
     */
    unproject(point) {
      let x
      let y
      if (Array.isArray(point)) {
        x = point[0]
        y = point[1]
      } else {
        x = point.x
        y = point.y
      }
      return this._proj.inverse([x, y])
    }

    /**
     * @description: 定义proj4
     * @param {*} code
     * @param {*} def
     * @return {*}
     */
    _projFromCodeDef(code, def) {
      if (def) {
        proj4.defs(code, def)
      } else if (proj4.defs[code] === undefined) {
        const urn = code.split(':')
        if (urn.length > 3) {
          code = `${urn[urn.length - 3]}:${urn[urn.length - 1]}`
        }
        if (proj4.defs[code] === undefined) {
          throw `No projection definition for code ${code}`
        }
      }
      return proj4(code)
    }

    // 判断是否为proj4对象
    _isProj4Obj(a) {
      return (
        typeof a.inverse !== 'undefined' && typeof a.forward !== 'undefined'
      )
    }
  }

  class MapboxglCustomCRS extends mapboxgl.CRS {
    _parseParams(args) {
      // proj4 type
      this._crsType = 'proj4'
      // epsg编号
      this.epsgCode = args[0]
      // def
      this.def = args[1]
      // 解析options
      const opts = args[2] || {}
      // 解析传入的参数
      this._parseOptions(opts)
    }

    /**
     * @description: 解析options
     * @param {*} opts
     * @return {*}
     */
    _parseOptions(opts) {
      super._parseOptions(opts)
      // 分辨率
      this._resolutions = opts.resolutions

      if (Array.isArray(this._resolutions)) {
        const resolutions = {}
        this._resolutions.forEach((v, i) => {
          resolutions[i] = v
        })
        this._resolutions = resolutions
      } else {
        this._resolutions = {}
      }

      if (!this._resolutions[0]) {
        throw new Error('自定义坐标系时,未设置分辨率数组')
      }

      if (!this.origin) {
        // 若原点不存在,设置bounds左上角为原点
        if (this.extent) {
          this.origin = [this.extent[0], this.extent[3]]
        } else {
          throw new Error('自定义坐标系时,未设置原点')
        }
      }
      // 解析第一张瓦片tileSize
      this.tileSize = opts.tileSize || 256
    }

    /**
     * @description: 获取投影系范围,如果投影系不满足长宽一致,会在这一步被处理成长宽一致
     * @return {*}
     */
    getExtent() {
      // 设置为正方形区域
      if (!this._rectifyExtent) {
        // 自定义坐标系时,重新设置范围
        const scale =
          this._resolutions[0 + this.getZoomOffset()] * this.tileSize
        const extent = [
          this.origin[0],
          this.origin[1] - scale,
          this.origin[0] + scale,
          this.origin[1]
        ]
        this._rectifyExtent = extent
      }
      return this._rectifyExtent
    }

    /**
     * @description: 设置投影对象
     * @return {*}
     */
    _setProjection() {
      this.projection = new MapboxglCustomProjection(this.getEpsgCode(), {
        origin: this.origin,
        def: this.def
      })
    }
  }

  if (!mapboxgl.Proj) {
    mapboxgl.Proj = {}
  }
  mapboxgl.Proj.CRS = MapboxglCustomCRS
  mapboxgl.Proj.Projection = MapboxglCustomProjection

  return MapboxglCustomCRS
}
export { mapboxCustomCRS }
构造函数
成员变量
方法
事件