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 }