代码片段

⌈地理⌋ 获取多个经纬度适合的缩放等级及中心点坐标

获取多个经纬度适合的缩放等级及中心点坐标。

javascript 复制代码
/**
 * 获取多个经纬度适合的缩放等级及中心点坐标
 * @param { { lat: number, lng: number }[] } points 多个经纬度
 * @returns { { center: { lat: number, lng: number }, zoom: number } } 适合的缩放等级
 */
export function getPointsCalculateZoom(points) {
  if(!points.length) throw new Error('请传入经纬度')

  const getZoom = (minPoint, maxPoint) => {
    const zoom = [
      50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 25000, 50000, 100000,
      200000, 500000, 1000000, 2000000
    ] //级别18到3。
    const distance = getDistance(minPoint, maxPoint)
    for (let i = 0, zoomLen = zoom.length; i < zoomLen; i++) {
      if (zoom[i] - distance > 0) {
        // 不同平台可能不太准,可在此处进行调整,或在调用完成后进行调整
        return 18 - i + 1
      }
    }
  }
  let maxLng = points[0].lng
  let minLng = points[0].lng
  let maxLat = points[0].lat
  let minLat = points[0].lat
  let res
  for (let i = points.length - 1; i >= 0; i--) {
    res = points[i]
    if (res.lng > maxLng) maxLng = res.lng
    if (res.lng < minLng) minLng = res.lng
    if (res.lat > maxLat) maxLat = res.lat
    if (res.lat < minLat) minLat = res.lat
  }
  const cenLng = (maxLng + minLng) / 2
  const cenLat = (maxLat + minLat) / 2
  const zoom = getZoom(
    { lng: minLng, lat: minLat },
    { lng: maxLng, lat: maxLat }
  )
  return {
    center: {
      lng: cenLng,
      lat: cenLat
    },
    zoom
  }
}
2025-11-24

⌈地理⌋ 获取两点间的距离

获取两点间的距离。

javascript 复制代码
/**
 * 获取两点间的距离
 * @param { { lat: number, lng: number } } point1 - 第一个点的经纬度
 * @param { { lat: number, lng: number } } point2 - 第二个点的经纬度
 * @param { boolean } kilometreFlag - 单位标志:true返回公里(km)并保留1位小数,false返回米(m)并取整
 * @returns { number } 两点间的距离
 */
export function getDistance(point1, point2, kilometreFlag = false) {
  const { lng: lng1, lat: lat1 } = point1
  const { lng: lng2, lat: lat2 } = point2
  // 将角度转换为弧度
  const rad = (d) => (d * Math.PI) / 180
  // 将经纬度从角度转换为弧度
  const radLat1 = rad(lat1)
  const radLat2 = rad(lat2)
  // 计算纬度和经度的差值(弧度)
  const a = radLat1 - radLat2
  const b = rad(lng1) - rad(lng2)
  // 使用哈弗辛公式计算两点间的球面距离
  let s =
    2 *
    Math.asin(
      Math.sqrt(
        Math.pow(Math.sin(a / 2), 2) +
          Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)
      )
    )
  // 乘以地球半径(6378.137公里)得到距离(公里)
  s = s * 6378.137
  // 根据单位标识返回不同单位和精度的结果
  if (kilometreFlag) {
    // 返回公里单位,保留1位小数
    s = Number(s.toFixed(1))
  } else {
    // 返回米单位,四舍五入取整
    s = Number(Math.round(s * 1000).toFixed(0))
  }
  return s
}
2025-11-24

⌈地理⌋ 获取多个经纬度的中间坐标

获取多个经纬度的中间坐标

javascript 复制代码
/**
 * 获取多个经纬度的中间坐标
 * @param {{lat: number, lng: number}[]} points 多个经纬度点
 * @returns {{lat: number, lng: number}} 中间坐标
 */
export function getPointsCalculateCenter(points) {
  const point_num = points.length; //坐标点个数
  let X = 0,
    Y = 0,
    Z = 0;
  for (let i = 0; i < points.length; i++) {
    if (!points[i]) {
      continue;
    }
    const point = points[i];
    const lat = (point.lat * Math.PI) / 180;
    const lng = (point.lng * Math.PI) / 180;
    const x = Math.cos(lat) * Math.cos(lng);
    const y = Math.cos(lat) * Math.sin(lng);
    const z = Math.sin(lat);
    X += x;
    Y += y;
    Z += z;
  }
  X = X / point_num;
  Y = Y / point_num;
  Z = Z / point_num;
  const tmp_lng = Math.atan2(Y, X);
  const tmp_lat = Math.atan2(Z, Math.sqrt(X * X + Y * Y));
  return { lat: (tmp_lat * 180) / Math.PI, lng: (tmp_lng * 180) / Math.PI };
}
2025-11-24

⌈地理⌋ WGS84坐标转换为GCJ02坐标

WGS84坐标转换为GCJ02坐标。

javascript 复制代码
/**
 * 判断是否在国外
 * @param { number } lng 经度
 * @param { number } lat 纬度
 * @returns { boolean } 是否在国外
 */
export function outOfChina(lng, lat) {
  return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271 || false;
}

/**
 * 转换纬度
 * @param { number } lng 经度
 * @param { number } lat 纬度
 * @returns { number } 转换后的纬度
 */
export function transformlat(lng, lat) {
  const PI = Math.PI;
  let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0;
  ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0;
  ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0;
  return ret;
}

/**
 * 转换经度
 * @param { number } lng 经度
 * @param { number } lat 纬度
 * @returns { number } 转换后的经度
 */
export function transformlng(lng, lat) {
  const PI = Math.PI;
  let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0;
  ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0;
  ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0;
  return ret;
}

/**
 * WGS84坐标转换为GCJ02坐标
 * @param { number } lng 经度
 * @param { number } lat 纬度
 * @returns { { lat: number, lng: number } } GCJ02坐标
 */
export function wgs84togcj02(lng, lat) {
  const PI = Math.PI;
  const a = 6378245.0;
  // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
  const ee = 0.00669342162296594323;
  if (outOfChina(lng, lat)) {
    return { lng, lat };
  } else {
    let dlat = transformlat(lng - 105.0, lat - 35.0);
    let dlng = transformlng(lng - 105.0, lat - 35.0);
    const radlat = (lat / 180.0) * PI;
    let magic = Math.sin(radlat);
    magic = 1 - ee * magic * magic;
    const sqrtmagic = Math.sqrt(magic);
    dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
    dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
    const mglat = lat + dlat;
    const mglng = lng + dlng;
    return { lng: mglng, lat: mglat };
  }
}
2025-11-24

⌈地理⌋ 获取坐标的是否在围栏内

判断指定经纬度位置,是否在电子围栏内部。

javascript 复制代码
/**
 * 获取坐标的是否在围栏内
 * @param { { lat: number, lng: number } } point 坐标
 * @param { { lat: number, lng: number }[] } APoints 围栏
 * @returns { boolean } 在围栏内返回true,否则false
 */
export function isPointInPolygon(point, APoints) {
  const { lat, lng } = point
  let iSum = 0
  let dLon1, dLon2, dLat1, dLat2, dLon
  if (APoints.length < 3) return false
  const iCount = APoints.length
  for (let i = 0; i < iCount; i++) {
    if (i == iCount - 1) {
      dLon1 = APoints[i].lng
      dLat1 = APoints[i].lat
      dLon2 = APoints[0].lng
      dLat2 = APoints[0].lat
    } else {
      dLon1 = APoints[i].lng
      dLat1 = APoints[i].lat
      dLon2 = APoints[i + 1].lng
      dLat2 = APoints[i + 1].lat
    }
    //以下语句判断A点是否在边的两端点的水平平行线之间,在则可能有交点,开始判断交点是否在左射线上
    if ((lat >= dLat1 && lat < dLat2) || (lat >= dLat2 && lat < dLat1)) {
      if (Math.abs(dLat1 - dLat2) > 0) {
        //得到 A点向左射线与边的交点的x坐标:
        dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - lat)) / (dLat1 - dLat2)
        if (dLon < lng) iSum++
      }
    }
  }
  if (iSum % 2 != 0) return true
  return false
}
2025-11-24