今天接到个需要需要计算两地之间的距离,算出要消耗多少东西,这个功能在微信小程序很好实现但是在web端没有现成的组件,只能自己一个个的去调,苦不堪言简直....,起初我是用的是axios来请求的腾讯api,axios弄好了我发布上线,发现有跨域,又跑到ng修改我们的跨域设置,设置完了好了之后想着松口气,没想到我们的服务没定位地址,服务器没有定位默认给的是北京,这显然不行,最后我是用的是jsonp请求,使用jsonp就没有跨域和当前用户定位的烦恼了,美滋滋。在写路况的时候发现他的路况图不会自己缩放自己的地图比例,让我好一顿找,最终发现了两点之间,显示在合适的层级的方法,相比较这一点高德确实不错啊,一步到位,可惜的就是有100km的限制。兄弟们看思路吧,先赞后看,江湖规矩哈
1.我们首先去腾讯控制台申请api的key,建立自己的应用 lbs.qq.com/dev/console…
2.我这个使用的webServiceApi,设置为授权IP,下面的输入框不要输入默认全部,或者输入自己本机的Ip
3.vue项目中index.html文件中引入自己的申请到的key,可参考官网api:lbs.qq.com/service/web…
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=自己申请的key"></script>
4.因为在ts项目中不识别引入的腾讯js我们要建立一个文件声明一下在文件外部建立一个TMap.d.ts文件
// 声明一下腾讯地图
declare global {
const TMap: any;
}
//自己封装的腾讯地图api
// MapService.ts
// import axiosInstance from "./requset";
import { jsonp } from "vue-jsonp";
const baseUrl = "https://apis.map.qq.com/ws";
export interface MapData {
// 定义腾讯地图接口返回的数据结构
// 根据实际情况进行定义
result: any;
data: any;
status: number;
}
export async function fetchMapData(params: {
address: string;
key: string;
}): Promise<MapData> {
try {
const response = await jsonp(baseUrl + "/location/v1/ip", {
key: params.key,
address: params.address,
output: "jsonp",
});
// 处理接口响应数据
return response;
} catch (error: any) {
// 处理请求错误
throw new Error(error);
}
}
export async function getLocation(params: {
location: string;
key: string;
get_poi: number;
poi_options: string;
}): Promise<MapData> {
try {
const response = await jsonp(baseUrl + "/geocoder/v1", {
key: params.key,
location: params.location,
get_poi: 1,
poi_options: params.poi_options,
output: "jsonp",
});
// 处理接口响应数据
return response;
} catch (error: any) {
// 处理请求错误
throw new Error(error);
}
}
export async function getSuggestion(params: {
keyword: string;
key: string;
}): Promise<MapData> {
try {
const response = await jsonp(baseUrl + "/place/v1/suggestion", {
key: params.key,
keyword: params.keyword,
output: "jsonp",
});
// 处理接口响应数据
return response;
} catch (error: any) {
// 处理请求错误
throw new Error(error);
}
}
export async function getGencoder(params: {
address: string;
key: string;
}): Promise<MapData> {
try {
const response = await jsonp(baseUrl + "/geocoder/v1", {
key: params.key,
address: params.address,
output: "jsonp",
});
// 处理接口响应数据
return response;
} catch (error: any) {
// 处理请求错误
throw new Error(error);
}
}
export async function getDriving(params: {
from: string;
key: string;
to: string;
}): Promise<MapData> {
try {
const response = await jsonp(baseUrl + "/direction/v1/driving", {
key: params.key,
from: params.from,
to: params.to,
output: "jsonp",
});
// 处理接口响应数据
return response;
} catch (error: any) {
// 处理请求错误
throw new Error(error);
}
}
5.创建一个地图
const dataMap: any = reactive({
map: "",
markerLayer: "",
zoom: "10",
latitude: "31.336843", //默认纬度
lngitude: "121.493889", //默认经度
});
const TMap = (window as any).TMap; // 声明TMap
// 生成地图
const init = () => {
let center = new TMap.LatLng(dataMap.latitude, dataMap.lngitude);
dataMap.map = new TMap.Map(document.getElementById("amp-container"), {
center: center, //设置地图中心点坐标
zoom: dataMap.zoom, //设置地图缩放级别
viewMode: "2D",
rotation: 20,
pitch: 30,
});
};
6.获取当前地址
const currentLotion = async () => {
try {
let params = {
key: "FMLBZ-IM2KH-ZL6D3-W6IND-RSK36-TPF3M", // 填申请到的腾讯key
address: "上海",
};
let { result } = await fetchMapData(params);
if (result) {
console.log(result);
// const loction = result.location.lat + "," + result.location.lng;
}
} catch (e) {
console.log(e);
}
}
7.获取附近的地址名称
const getLocationAddress = async (value: string) => {
let params = {
key: "FMLBZ-IM2KH-ZL6D3-W6IND-RSK36-TPF3M", // 填申请到的腾讯key
location: value,
get_poi: 1,
poi_options: "policy=5",
};
let { result } = await getLocation(params);
addressList.value = result.pois;
};
8.获取两地的距离以及路线图
const toDriving = async () => {
//这里面的值为pinia中存储的值,将你的重点坐标起点坐标放入
let params = {
from:
storeData.startLoction.location.lat +
"," +
storeData.startLoction.location.lng,
to:
storeData.endLocation.location.lat +
"," +
storeData.endLocation.location.lng,
key: "FMLBZ-IM2KH-ZL6D3-W6IND-RSK36-TPF3M", // 填申请到的腾讯key
get_speed: 1,
};
let { status, result } = await getDriving(params);
if (status == 0) {
distanceLine.value = result.routes[0].distance;
// dataMap.zoom = calculateZoomLevel(result.routes[0].distance).toString();
// reloadMap();
var coors = result.routes[0].polyline,
pl = [];
//坐标解压(返回的点串坐标,通过前向差分进行压缩,因此需要解压)
var kr = 1000000;
for (var i = 2; i < coors.length; i++) {
coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
}
//将解压后的坐标生成LatLng数组
for (var i = 0; i < coors.length; i += 2) {
pl.push(new TMap.LatLng(coors[i], coors[i + 1]));
}
new TMap.MultiPolyline({
id: "polyline-layer", //图层唯一标识
map: dataMap.map, //绘制到目标地图
//折线样式定义
styles: {
style_blue: new TMap.PolylineStyle({
color: "#3777FF", //线填充色
width: 8, //折线宽度
borderWidth: 5, //边线宽度
borderColor: "#FFF", //边线颜色
lineCap: "round", //线端头方式
}),
},
//折线数据定义
geometries: [
{
id: "pl_1", //折线唯一标识,删除时使用
styleId: "style_blue", //绑定样式名
paths: pl,
},
],
});
showMarker();
}
};
var bounds = new TMap.LatLngBounds();
const showMarker = () => {
markerLayer();
markerArr.forEach(function (item) {
//若坐标点不在范围内,扩大bounds范围
if (bounds.isEmpty() || !bounds.contains(item.position)) {
bounds.extend(item.position);
}
});
//自适应设置地图可视范围
dataMap.map?.fitBounds(bounds, {
padding: 100, // 自适应边距
});
};
9.两地坐标位置展示
const markerArr = [
{
id: "marker1", //标记1
styleId: "marker", //指定样式id
position: new TMap.LatLng(
storeData?.startLoction?.location?.lat || 39.984104,
storeData?.startLoction?.location?.lng || 116.307503
), //点标记坐标位置
src: "http://oss.cn-north-3.inspurcloudoss.com/eccloud/ce4d79a7cce849b3a512d9b51c2da9c0?",
},
{
id: "marker2", //标记1
styleId: "marker", //指定样式id
src: "http://oss.cn-north-3.inspurcloudoss.com/eccloud/ce4d79a7cce849b3a512d9b51c2da9c0?",
position: new TMap.LatLng(
storeData?.endLocation?.location?.lat || 39.794104,
storeData?.endLocation?.location?.lng || 116.287503
), //点标记坐标位置
},
];
// 标记地图
const markerLayer = () => {
dataMap.markerLayer = new TMap.MultiMarker({
map: dataMap.map, //指定地图容器
//样式定义
styles: {
myStyle: new TMap.MarkerStyle({
width: 25,
height: 35,
anchor: { x: 16, y: 32 },
src: "http://oss.cn-north-3.inspurcloudoss.com/eccloud/ce4d79a7cce849b3a512d9b51c2da9c0?",
}),
},
//点标记数据数组
geometries: markerArr,
});
};
//监听两地位置变化重新生成路线图
watchEffect(() => {
if (storeData.startLoction.address && storeData.endLocation.address) {
dataMap.map = null;
toDriving();
}
});
效果展示: