coordinateUtils.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /**
  2. * 坐标转换工具类
  3. * 将高德地图坐标(GCJ-02)转换为WGS84坐标
  4. */
  5. // 坐标转换常量
  6. const PI = Math.PI
  7. const A = 6378245.0 // WGS84椭球长半轴
  8. const EE = 0.00669342162296594323 // WGS84椭球扁率
  9. /**
  10. * 判断坐标是否在中国境内
  11. * @param {number} lng 经度
  12. * @param {number} lat 纬度
  13. * @returns {boolean} 是否在中国境内
  14. */
  15. function isInChina(lng, lat) {
  16. return lng >= 73.66 && lng <= 135.05 && lat >= 3.86 && lat <= 53.55
  17. }
  18. /**
  19. * 将GCJ-02坐标转换为WGS84坐标
  20. * @param {number} gcjLng GCJ-02经度
  21. * @param {number} gcjLat GCJ-02纬度
  22. * @returns {Object} WGS84坐标 {lng, lat}
  23. */
  24. function gcj02ToWgs84(gcjLng, gcjLat) {
  25. if (!isInChina(gcjLng, gcjLat)) {
  26. return {
  27. lng: gcjLng,
  28. lat: gcjLat
  29. }
  30. }
  31. let dLat = transformLat(gcjLng - 105.0, gcjLat - 35.0)
  32. let dLng = transformLng(gcjLng - 105.0, gcjLat - 35.0)
  33. const radLat = gcjLat / 180.0 * PI
  34. let magic = Math.sin(radLat)
  35. magic = 1 - EE * magic * magic
  36. const sqrtMagic = Math.sqrt(magic)
  37. dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI)
  38. dLng = (dLng * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI)
  39. const wgsLat = gcjLat - dLat
  40. const wgsLng = gcjLng - dLng
  41. return {
  42. lng: wgsLng,
  43. lat: wgsLat
  44. }
  45. }
  46. /**
  47. * 纬度转换函数
  48. * @param {number} x
  49. * @param {number} y
  50. * @returns {number}
  51. */
  52. function transformLat(x, y) {
  53. let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x))
  54. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0
  55. ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0
  56. ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0
  57. return ret
  58. }
  59. /**
  60. * 经度转换函数
  61. * @param {number} x
  62. * @param {number} y
  63. * @returns {number}
  64. */
  65. function transformLng(x, y) {
  66. let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x))
  67. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0
  68. ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0
  69. ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0
  70. return ret
  71. }
  72. /**
  73. * 转换坐标点数组
  74. * @param {Array} points 坐标点数组,每个点包含lng和lat属性
  75. * @returns {Array} 转换后的坐标点数组
  76. */
  77. function convertPointsToWgs84(points) {
  78. if (!Array.isArray(points)) {
  79. return []
  80. }
  81. return points.map(point => {
  82. if (!point || typeof point.lng !== 'number' || typeof point.lat !== 'number') {
  83. return point // 如果点数据不完整,返回原数据
  84. }
  85. const converted = gcj02ToWgs84(point.lng, point.lat)
  86. return {
  87. ...point,
  88. lng: converted.lng,
  89. lat: converted.lat
  90. }
  91. })
  92. }
  93. /**
  94. * 转换单个坐标点
  95. * @param {Object} point 坐标点对象 {lng, lat, ...}
  96. * @returns {Object} 转换后的坐标点对象
  97. */
  98. function convertPointToWgs84(point) {
  99. if (!point || typeof point.lng !== 'number' || typeof point.lat !== 'number') {
  100. return point
  101. }
  102. const converted = gcj02ToWgs84(point.lng, point.lat)
  103. return {
  104. ...point,
  105. lng: converted.lng,
  106. lat: converted.lat
  107. }
  108. }
  109. export default {
  110. gcj02ToWgs84,
  111. convertPointsToWgs84,
  112. convertPointToWgs84,
  113. isInChina
  114. }