Skip to content

投影

坐标系转换

点我查看代码
vue
<script lang="ts" setup>
import { EPSG_3857ToEPSG_4326, EPSG_4326ExtentToEPSG_3857, EPSG_4326ToEPSG_3857, EPSG_3857ExtentToEPSG_4326, createTileGrid, registerEPSG_3395 } from '@summeruse/ol'
import { NButton, NFormItem, NInputNumber } from 'naive-ui'
import { computed, ref } from 'vue'

// 坐标转换
const coord = ref([116.404, 39.915])
const mercator = computed(() => EPSG_4326ToEPSG_3857(coord.value))

const mercator2 = ref([12959638.8957, 4855982.5492])
const coord2 = computed(() => EPSG_3857ToEPSG_4326(mercator2.value))

// 范围转换
const bbox = computed(() => {
  const [lon, lat] = coord.value
  const d = 0.5
  return [lon - d, lat - d, lon + d, lat + d] as [number, number, number, number]
})
const mercatorBbox = computed(() => EPSG_4326ExtentToEPSG_3857(bbox.value))
const backBbox = computed(() => EPSG_3857ExtentToEPSG_4326(mercatorBbox.value))

// 注册 EPSG:3395
const registered = ref(false)
function doRegister() {
  registerEPSG_3395()
  registered.value = true
}

// 创建 TileGrid
const tileGridInfo = computed(() => {
  const grid = createTileGrid('EPSG:3395')
  if (!grid) return '未注册 EPSG:3395,请先点击注册'
  return `TileSize: ${grid.getTileSize(0)}, Extent: [${grid.getExtent().join(', ')}]`
})
</script>

<template>
  <NFormItem label="WGS84坐标转墨卡托">
    <NInputNumber v-model:value="coord[0]" :step="0.1" /> 经度
    <NInputNumber v-model:value="coord[1]" :step="0.1" /> 纬度
  </NFormItem>
  <NFormItem label="=">
    <span> {{ mercator[0] }} , {{ mercator[1] }} </span>
  </NFormItem>
  <NFormItem label="墨卡托转WGS84">
    <NInputNumber v-model:value="mercator2[0]" :step="0.1" /> x
    <NInputNumber v-model:value="mercator2[1]" :step="0.1" /> y
  </NFormItem>
  <NFormItem label="=">
    <span> {{ coord2[0] }} , {{ coord2[1] }} </span>
  </NFormItem>
  <NFormItem label="范围转换">
    <span>4326 bbox: [{{ bbox.join(', ') }}]</span>
  </NFormItem>
  <NFormItem label="→ 3857">
    <span>[{{ mercatorBbox.map(v => v.toFixed(0)).join(', ') }}]</span>
  </NFormItem>
  <NFormItem label="→ 4326 回转换">
    <span>[{{ backBbox.map(v => v.toFixed(4)).join(', ') }}]</span>
  </NFormItem>
  <NFormItem label="EPSG:3395">
    <NButton :disabled="registered" @click="doRegister">
      {{ registered ? '已注册' : '注册 EPSG:3395' }}
    </NButton>
  </NFormItem>
  <NFormItem label="TileGrid">
    <span>{{ tileGridInfo }}</span>
  </NFormItem>
</template>

API

坐标转换

名称类型说明
EPSG_4326ToEPSG_3857(coordinate: Coordinate) => CoordinateEPSG:4326 坐标转 EPSG:3857
EPSG_3857ToEPSG_4326(coordinate: Coordinate) => CoordinateEPSG:3857 坐标转 EPSG:4326

范围转换

名称类型说明
EPSG_4326ExtentToEPSG_3857(extent: Extent) => ExtentEPSG:4326 范围转 EPSG:3857
EPSG_3857ExtentToEPSG_4326(extent: Extent) => ExtentEPSG:3857 范围转 EPSG:4326

其他

名称类型说明
registerEPSG_3395() => void注册 EPSG:3395 椭球墨卡托投影(通过 proj4),重复调用不生效
createTileGrid(ProjectionLike?: Projection | string) => XYZTileGrid | undefined根据投影创建 TileGrid,当前支持 EPSG:3395
proj4typeof proj4直接导出 proj4 实例,用于自定义投影注册

源代码

点我查看代码
ts
import type { Coordinate } from 'ol/coordinate'
import type { Extent } from 'ol/extent'
import type { Projection } from 'ol/proj'
import { get as getProjection, transform, transformExtent } from 'ol/proj'
import { register } from 'ol/proj/proj4'
import { createXYZ } from 'ol/tilegrid'
import proj4 from 'proj4'

import { EPSG_3395, EPSG_3857, EPSG_4326 } from '../../constants'
/**  EPSG_4326转EPSG_3857 */
export function EPSG_4326ToEPSG_3857(coordinate: Coordinate) {
  return transform(coordinate, EPSG_4326, EPSG_3857)
}

/** EPSG_3857转EPSG_4326 */
export function EPSG_3857ToEPSG_4326(coordinate: Coordinate) {
  return transform(coordinate, EPSG_3857, EPSG_4326)
}

/** EPSG_4326范围转EPSG_3857 */
export function EPSG_4326ExtentToEPSG_3857(extent: Extent) {
  return transformExtent(extent, EPSG_4326, EPSG_3857)
}

/** EPSG_3857范围转EPSG_4326 */
export function EPSG_3857ExtentToEPSG_4326(extent: Extent) {
  return transformExtent(extent, EPSG_3857, EPSG_4326)
}

export function registerEPSG_3395() {
  if (getProjection(EPSG_3395)) {
    return
  }
  proj4.defs(
    'EPSG:3395',
    // cSpell:disable-next-line
    '+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 ' + '+datum=WGS84 +units=m +no_defs +type=crs',
  )
  register(proj4)
}

export function createTileGrid(ProjectionLike?: Projection | string) {
  if (ProjectionLike === EPSG_3395) {
    registerEPSG_3395()
    return createXYZ({
      extent: [-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892],
    })
  }
}

export { proj4 }

Released under the ISC License.