blog
blog copied to clipboard
两个位置经纬度之间直线距离计算
两个位置经纬度之间直线距离计算
需要计算两个经纬度之间的直线距离,实现类是定位打卡效果;
代码如下:
import MapUtils from '@/utils/mapUtils';
const calculateTwoPlaceDistance = () => {
// 调用距离计算接口,注意两个坐标类型要一致,都是腾讯地图位置或者高德地图,否则需要自己转换
MapUtils.calculateDistance({
from: '24.622473,118.037944', // 起点坐标
to: '24.622154,118.039084', // 终点坐标
success: res => { // 成功后的回调
let hw = res.result.elements[0].distance; // 拿到距离(米)
if (hw && hw !== -1) {
if (hw < 1000) {
hw += 'm';
} else {
// 转换成公里
hw = `${(hw / 2 / 500).toFixed(2)}km`;
}
} else {
hw = '距离太近或请刷新重试';
}
alert(`当前位置与办公地点距离:${hw}`);
},
});
};
mapUtils
代码如下:
var ERROR_CONF = {
KEY_ERR: 311,
KEY_ERR_MSG: 'key格式错误',
PARAM_ERR: 310,
PARAM_ERR_MSG: '请求参数信息有误',
SYSTEM_ERR: 600,
SYSTEM_ERR_MSG: '系统错误',
WX_ERR_CODE: 1000,
WX_OK_CODE: 200
};
var EARTH_RADIUS = 6378136.49;
var Utils = {
/**
* 构造错误数据结构
* @param {Number} errCode 错误码
* @param {Number} errMsg 错误描述
*/
buildErrorConfig(errCode, errMsg) {
return {
status: errCode,
message: errMsg
};
},
/**
* 回调函数默认处理
*/
polyfillParam(param) {
param.success = param.success || function () { };
param.fail = param.fail || function () { };
param.complete = param.complete || function () { };
},
/**
* 验证param对应的key值是否为空
*
* @param {Object} param 接口参数
* @param {String} key 对应参数的key
*/
checkParamKeyEmpty(param, key) {
if (!param[key]) {
var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, `${ERROR_CONF.PARAM_ERR_MSG + key}参数格式有误`);
param.fail(errconf);
param.complete(errconf);
return true;
}
return false;
},
/**
* 计算角度
*/
rad(d) {
return d * Math.PI / 180.0;
},
/**
* 得到终点query字符串
* @param {Array|String} 检索数据
*/
location2query(data) {
if (typeof data === 'string') {
return data;
}
let query = '';
for (let i = 0; i < data.length; i++) {
var d = data[i];
if (query) {
query += ';';
}
if (d.location) {
query = `${query + d.location.lat},${d.location.lng}`;
}
if (d.latitude && d.longitude) {
query = `${query + d.latitude},${d.longitude}`;
}
}
return query;
},
/**
* 处理终点location数组
* @return 返回终点数组
*/
getEndLocation(location){
var to = location.split(';');
var endLocation = [];
for (let i = 0; i < to.length; i++) {
endLocation.push({
lat: parseFloat(to[i].split(',')[0]),
lng: parseFloat(to[i].split(',')[1])
});
}
return endLocation;
},
/**
* 计算两点间直线距离
* @param a 表示纬度差
* @param b 表示经度差
* @return 返回的是距离,单位m
*/
getDistance(latFrom, lngFrom, latTo, lngTo) {
var radLatFrom = this.rad(latFrom);
var radLatTo = this.rad(latTo);
var a = radLatFrom - radLatTo;
var b = this.rad(lngFrom) - this.rad(lngTo);
let distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLatFrom) * Math.cos(radLatTo) * Math.pow(Math.sin(b / 2), 2)));
distance *= EARTH_RADIUS;
distance = Math.round(distance * 10000) / 10000;
return parseFloat(distance.toFixed(0));
},
/**
* 获取location参数
*/
getLocationParam(location) {
if (typeof location === 'string') {
var locationArr = location.split(',');
if (locationArr.length === 2) {
location = {
latitude: location.split(',')[0],
longitude: location.split(',')[1]
};
} else {
location = {};
}
}
return location;
},
/**
* 验证location值
*
* @param {Object} param 接口参数
*/
checkLocation(param) {
var location = this.getLocationParam(param.location);
if (!location || !location.latitude || !location.longitude) {
var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, `${ERROR_CONF.PARAM_ERR_MSG} location参数格式有误`);
param.fail(errconf);
param.complete(errconf);
return false;
}
return true;
},
/**
* 处理用户参数是否传入坐标进行不同的处理
*/
locationProcess(param, locationsuccess, locationfail, locationcomplete) {
var that = this;
locationfail = locationfail || function (res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE;
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
};
locationcomplete = locationcomplete || function (res) {
if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
}
};
if (!param.location) {
that.getWXLocation(locationsuccess, locationfail, locationcomplete);
} else if (that.checkLocation(param)) {
var location = Utils.getLocationParam(param.location);
locationsuccess(location);
}
}
};
var MapUtils = {
/**
*
* 新增直线距离计算。
*
* @param {Object} options 接口参数对象
*
*/
calculateDistance(options) {
options = options || {};
Utils.polyfillParam(options);
if (Utils.checkParamKeyEmpty(options, 'to')) {
return;
}
var requestParam = {
mode: options.mode || 'walking',
to: Utils.location2query(options.to),
output: 'json',
};
if (options.from) {
options.location = options.from;
}
// 计算直线距离
var locationsuccess = function (result) {
var locationTo = Utils.getEndLocation(requestParam.to);// 处理终点坐标
var data = {
message: 'query ok',
result: {
elements: []
},
status: 0
};
for (var i = 0; i < locationTo.length; i++) {
data.result.elements.push({// 将坐标存入
distance: Utils.getDistance(result.latitude, result.longitude, locationTo[i].lat, locationTo[i].lng),
duration: 0,
from: {
lat: result.latitude,
lng: result.longitude
},
to: {
lat: locationTo[i].lat,
lng: locationTo[i].lng
}
});
}
var calculateResult = data.result.elements;
var distanceResult = [];
for (var i = 0; i < calculateResult.length; i++) {
distanceResult.push(calculateResult[i].distance);
}
return options.success(data, {
calculateResult,
distanceResult
});
};
Utils.locationProcess(options, locationsuccess);
}
};
export default MapUtils;