最近有一个需求是从app分享位置到微信,打开微信可以实现导航的功能,查询资料发现没有办法可以直接发送位置到微信,但是微信网页开发可以实现在微信内部用网页打开腾讯内置地图,进而实现导航的功能,所以决定通过分享H5到微信来解决问题。
思路:uniapp分享链接到微信,链接中带有经纬度和位置名称,在微信中打开链接,通过参数打开微信内置地图。
微信sdk使用说明文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
需要手机微信调试的可以引入vconsole.js,可以显示控制台:https://unpkg.com/vconsole@latest/dist/vconsole.min.js
<script>
// VConsole 默认会挂载到 `window.VConsole` 上
var vConsole = new window.VConsole();
</script>
具体步骤不详说,可看文档操作。
由于用到的查看位置wx.openLocation
需要用到鉴权。同一个地址的网页只需注入一次就行,如果地址有变化,则需要重新注入权限验证配置。
wx.config({
debug: true, // 开启调试模式,调用的所有 api 的返回值会在客户端 alert 出来,若要查看传入的参数,可以在 pc 端打开,参数信息会通过 log 打出,仅在 pc 端时才会打印。
appId: res.data.appId, // 必填,公众号的唯一标识
timestamp: res.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.signature,// 必填,签名
jsApiList: [
'openLocation'
] // 必填,需要使用的 JS 接口列表,这里只用到了openLocation
});
其中appId
、timestamp
、nonceStr
、signature
都是通过传入当前网页的地址(window.location.href
),调用后端接口的返回值。
由于我们是页面一加载就调用wx.openLocation
接口,所以需要在wx.ready
中调用。
wx.ready(function(){
// config信息验证后会执行 ready 方法,所有接口调用都必须在 config 接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在 ready 函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在 ready 函数中。
openLocation();
});
wx.error(function(res){
// config信息验证失败会执行 error 函数,如签名过期导致验证失败,具体错误信息可以打开 config 的debug模式查看,也可以在返回的 res 参数中查看,对于 SPA 可以在这里更新签名。
});
// 打开地图方法
function openLocation() {
var latitude = getQueryString("latitude");
var longitude = getQueryString("longitude");
var name = getQueryString("name");
wx.openLocation({
latitude: latitude, // 纬度,浮点数,范围为90 ~ -90
longitude: longitude, // 经度,浮点数,范围为180 ~ -180
name: name, // 位置名
address: '', // 地址详情说明
scale: 14, // 地图缩放级别,整型值,范围从1~28。默认为最大
infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
});
}
// 截取地址参数
function getQueryString(name) {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(decodeURI(r[2]));
return null;
}
}
接口返回慢的话,用户可能会看到比较长时间的白页,所以需要一个加载的loading。
@keyframes spinner-line-fade-more {
0%, 100% { opacity: 0; /* minimum opacity */ }
1% { opacity: 1; }
}
@keyframes spinner-line-fade-quick {
0%, 39%, 100% { opacity: 0.25; /* minimum opacity */ }
40% { opacity: 1; }
}
@keyframes spinner-line-fade-default {
0%, 100% { opacity: 0.22; /* minimum opacity */ }
1% { opacity: 1; }
}
@keyframes spinner-line-shrink {
0%, 25%, 100% {
/* minimum scale and opacity */
transform: scale(0.5);
opacity: 0.25;
}
26% {
transform: scale(1);
opacity: 1;
}
}
// 引入了spin.js
var opts = {
lines: 12, // 花瓣数目
length: 8, // 花瓣长度
width: 4, // 花瓣宽度
radius: 8, // 花瓣距中心半径
corners: 1, // 花瓣圆滑度 (0-1)
rotate: 0, // 花瓣旋转角度
direction: 1, // 花瓣旋转方向 1: 顺时针, -1: 逆时针
color: '#666666', // 花瓣颜色
speed: 1, // 花瓣旋转速度
trail: 60, // 花瓣旋转时的拖影(百分比)
shadow: false, // 花瓣是否显示阴影
hwaccel: false, //spinner 是否启用硬件加速及高速旋转
className: 'spinner', // spinner css 样式名称
zIndex: 2e9, // spinner的z轴 (默认是2000000000)
top: '30%', // spinner 相对父容器Top定位 单位 px
left: '50%', // spinner 相对父容器Left定位 单位 px
position: 'fixed', // element position
progress: true, // show progress tracker
progressTop: 0, // offset top for progress tracker
progressLeft: 0 // offset left for progress tracker
};
var target = document.getElementById('wrapper'); // loading的承载盒子,设置了宽100vw,高100传的div
var spinner = new Spin.Spinner(opts).spin(target); //创建loading,loading显示
// 关闭loading,在打开地图(openLocation)前调用
spinner.spin();
const weburl = baseUrl+'/wxLocation/index.html?latitude='+latitudes+"&longitude="+longitudes+"&name="+name
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 0,
href: weburl, // 分享链接
title: name, // 分享标题
summary: "快去查看"+ name +"的位置吧!", //分享文字
imageUrl: imageUrl, //分享图标
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
});