/* * ✨ Gis地图常用辅助工具类函数 ✨ * */ /** * 计算一组地理点的中心点(经纬度)。 * @description * 该函数接受一个包含地理点的数组,计算并返回所有点的平均经纬度作为中心点坐标。 * 支持输入二维数组 `[lng, lat]` 或对象数组(包含 `lng` 和 `lat` 字段),并允许使用自定义函数提取坐标。 * * @param {Array} points - 包含地理点的数组。可以是二维数组格式`[lng, lat]`或对象数组(每个对象至少包含 `lng` 和 `lat` 字段)。 * @param {Function} [getCoordinates] - 可选参数,用于从对象数组中提取经纬度的函数。默认提取对象的 `lng` 和 `lat` 字段。 * @returns {Array | null} - 返回中心点的经纬度数组 `[lng, lat]`。如果输入为空数组或没有有效的经纬度数据,返回null。 * * @example * // 计算二维数组格式的中心点 * const coords = [ * [116.397, 39.907], * [116.387, 39.917], * [116.407, 39.917] * ]; * const center = getCenterPoint(coords); * console.log(center); // 输出: [116.397, 39.91366666666667] * * @example * // 计算对象数组格式的中心点 * const locations = [ * { lng: 116.397, lat: 39.907 }, * { lng: 116.387, lat: 39.917 }, * { lng: 116.407, lat: 39.917 } * ]; * const center = getCenterPoint(locations, loc => [loc.lng, loc.lat]); * console.log(center); // 输出: [116.397, 39.91366666666667] */ export function getCenterPoint(points, getCoordinates) { // 如果输入不是数组或数组为空,返回空数组 if (!(Array.isArray(points) && points.length)) return null // 验证经纬度数组是否合法 const isValidCoords = coords => Array.isArray(coords) && coords.length === 2 && coords.every(coord => coord != null) // 参数归一化:根据输入的数据类型,处理为二维数组格式 // 如果是二维数组,直接过滤出有效的坐标点 // 如果是对象数组,使用getCoordinates函数(如果提供)提取坐标,否则默认提取lng和lat字段 const normalizedPoints = Array.isArray(points[0]) ? points.filter(isValidCoords) // 过滤掉无效的二维坐标数组 : points.flatMap(point => { // 提取坐标信息,默认提取对象中的lng和lat字段 const coords = getCoordinates ? getCoordinates(point) : [point.lng, point.lat] // 只保留有效的坐标数组 return isValidCoords(coords) ? [coords] : [] }) // 使用reduce迭代累加所有点的经度和纬度 const total = normalizedPoints.reduce((acc, [lng, lat]) => { acc.lngSum += +lng // 累加经度 acc.latSum += +lat // 累加纬度 return acc }, {lngSum: 0, latSum: 0}) // 如果没有有效的经纬度数据,返回空数组 if (!normalizedPoints.length) return null // 计算中心点的经纬度:使用累加的经纬度总和除以有效点的数量 const centerLng = total.lngSum / normalizedPoints.length const centerLat = total.latSum / normalizedPoints.length // 返回中心点的经纬度数组 return [centerLng, centerLat] }