首先是后台管理实现选择打卡区域圆:
<div style="margin-top: 10px;margin-left:0px;height: 500px;width: 1100px;" id="container"></div>
//百度地图渲染
var map = new BMap.Map("container");
window.map = map;
var point = new BMap.Point(112.559488,32.973367);
map.centerAndZoom(point, 19);
map.addControl(new BMap.MapTypeControl({
mapTypes:[
BMAP_NORMAL_MAP,
BMAP_HYBRID_MAP
]
}));
//开启鼠标滚轮缩放
map.enableScrollWheelZoom(true);
//左上角添加比例尺
var top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});
map.addControl(top_left_control);
//单击获取点击的经纬度
map.addEventListener("click",function(e){
var location = {lat:e.point.lat,lng:e.point.lng};//获取点击点位置组成对象
var rad = $('#rad').val();
if(rad === ''){
layer.msg('请先填写区域圆半径');
}
//画到地图上面,先清除
map.clearOverlays();
//创建圆对象
circle = new BMap.Circle(location, rad, {
strokeColor: "red",
strokeWeight: 2,
fillColor: "#E2E8F1",
fillOpacity: 0.4
});
var marker = new BMap.Marker(location);// 创建标注
map.addOverlay(marker);
map.addOverlay(circle);
$("#lan").val(e.point.lng);
$("#lat").val(e.point.lat);
});
选择圆心坐标画圆,实现效果:
在后台渲染出百度地图并实现点击标注,画圆,是比较简单的,遇到一个坑点就是放到https上面的时候一直出问题,官方说只需要把引入改成
<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=3.0&ak=你的ak值&s=1"></script>
我遇到的在改成这样的情况下,还是有少部分的请求是http请求因为被浏览器检测不安全拦截了。把浏览器的拦截关了也没什么问题了。要不关闭拦截的话,在js最前面加上window.HOST_TYPE = '2';就好了。这是解释的原文:https://juejin.im/post/5a9259ef5188251c85637e25
在微信端通过定位获取到用户的位置,再根据用户的位置算出距离,看是不是在后台设置的打卡区域圆里面,判断打卡位置是否合理。
定位首先尝试的是百度地图的定位接口,做好之后。测试才发现定位存在很大的偏差,偶尔还出现超时的现象。只有在一个苹果手机上测试的时候定位还比较准。
后面换了一种思路,用微信jssdk获取比较准确的位置(单位为wgs84),再通过百度提供的转化接口将wgs84转化为百度地图使用的bd09。这样就获取到了比较准确的位置坐标,再用坐标算出实际距离在不在规定区域就好了。
这里贴出代码:
//提交位置信息到后台的表单
<form method="post" action="你的url">
<input type="hidden" name="lat" value="" id="lat">
<input type="hidden" name="lan" value="" id="lan">
<button class="acsign-btn" type="submit">打卡</button>
</form>
//引入jssdk
<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
//引入百度地图要用https
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=你的ak&s=1"></script>
<script>
var preLocation;//存储上一个位置
//配置jssdk前端
$.ajax({
type: 'post',
url: '你的url',
data: {url:encodeURIComponent(location.href.split('#')[0])},
async: true,
success: function (res) {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.appid, // 必填,公众号的唯一标识
timestamp: res.timestamp, // 必填,生成签名的时间戳
nonceStr: res.noncestr, // 必填,生成签名的随机串
signature: res.signature,// 必填,签名
jsApiList: ['getLocation','openLocation'] // 必填,需要使用的JS接口列表
});
},
error: function (res) {
alert('操作失败');
}
});
$(function () {
//百度地图渲染
var map = new BMap.Map("area-bd");
window.map = map;
var point = new BMap.Point('{$acsign.lan}','{$acsign.lat}');
map.centerAndZoom(point, 17);
map.addControl(new BMap.MapTypeControl({
mapTypes:[
BMAP_NORMAL_MAP,
BMAP_HYBRID_MAP
]
}));
//开启鼠标滚轮缩放
map.enableScrollWheelZoom(true);
//左上角添加比例尺
var top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});
map.addControl(top_left_control);
// 初始化圆区域
// 创建圆对象
circle1 = new BMap.Circle({lat:'{$acsign.lat}',lng:'{$acsign.lan}'}, {$acsign.rad}, {
strokeColor: "red",
strokeWeight: 2,
fillColor: "#E2E8F1",
fillOpacity: 0.4
});
map.clearOverlays();//清除所有
map.addOverlay(new BMap.Marker(point));// 创建标注
map.addOverlay(circle1);
wx.ready(function () {
reGetLocation();
});
});
//点击刷新图标刷新自己的位置
$('.icon-refresh').click(function () {
reGetLocation();
});
//获得自己位置并标注在地图上的函数
function reGetLocation() {
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: function (res) {
console.log(res);
$.ajax({
type: 'post',
url: '你的url',
data: {location:res.longitude+','+res.latitude},
async: true,
success: function (result) {
if(result.code == 0){
var point1 = new BMap.Point(result.data.result[0].x,result.data.result[0].y);
var myLocation = new BMap.Marker(point1);
if(preLocation){
map.removeOverlay(preLocation);
}
// alert(point1.lat+','+point1.lng);
map.addOverlay(myLocation);
map.panTo(point1);
$('#lat').val(result.data.result[0].y);
$('#lan').val(result.data.result[0].x);
preLocation = myLocation;
}else {
$.toast(result.msg, "text");
}
}
});
}
});
}
</script>
后端:
百度提供的坐标转化接口curl实现:
//在tp3.2实现的
public function zhuan(){
$location = I('location','','trim');
if(empty($location)){
$this->result([],'坐标参数错误',1009);
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://api.map.baidu.com/geoconv/v1/?coords=$location&from=1&to=5&ak=你的ak",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Accept-Encoding: gzip, deflate",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Content-Type: application/x-www-form-urlencoded",
"Host: api.map.baidu.com",
"Postman-Token: 4b29fe32-72d9-4aa6-a2ef-6303ee1621aa,60af1ece-b2ce-4afb-9c40-516f178c4a88",
"User-Agent: PostmanRuntime/7.17.1",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
$this->result([], "cURL Error #:" . $err,1007);
} else {
$this->result(json_decode($response,true),'转化成功',0);
}
}
计算两个经纬度坐标之间的距离:
/**
* 计算两组经纬度坐标 之间的距离
* params :lat1 纬度1; lng1 经度1; lat2 纬度2; lng2 经度2; len_type (1:m or 2:km);
* return m or km
*/
protected function getDistance($lat1, $lng1, $lat2, $lng2, $len_type = 1, $decimal = 2){
$EARTH_RADIUS=6378.137;
$PI=3.1415926;
$radLat1 = $lat1 * $PI / 180.0;
$radLat2 = $lat2 * $PI / 180.0;
$a = $radLat1 - $radLat2;
$b = ($lng1 * $PI / 180.0) - ($lng2 * $PI / 180.0);
$s = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
$s = $s * $EARTH_RADIUS;
$s = round($s * 1000);
if ($len_type > 1)
{
$s /= 1000;
}
return round($s,$decimal);
}
微信jssdk的后台配置就不贴代码了,在我之前的博客中有讲到:https://blog.csdn.net/a1234name/article/details/98771695
对于百度地图的操作多看看文档应该就行了,就是应该会遇到一些坑点会比较麻烦。