准备工作:
- 高德开发者账号(必须经过认证)
- 高德web_service_key(web服务key)
参考文档:
猎鹰服务-服务端 https://lbs.amap.com/api/track/lieying-kaifa/api/service
js多边形绘制https://lbs.amap.com/demo/javascript-api-v2/example/overlay-editor/polygon-editor-avoidpolygon/
注意事项:
- 申请好对应的key之后,需要先创建对应的service,一个key之下最多有15个service
- 每个service之间的数据并不互通
- 正常开发测试不会触发高德流量预警
创建猎鹰服务service
public function createService()
{
$params = [
'name' => input('name'),
'desc' => input('desc'),//创建不同的service时,请更换描述
'key' => input('key'),//webapi key
];
$url = 'https://tsapi.amap.com/v1/track/service/add';
$arr = [
'name' => $params['name'],
'desc' => $params['desc'],
'key' => $params['key'],
];
$res = $this->send_post($url, $arr);//res中包含唯一值sid,请务必将sid保存
print_r($res);exit;
}
公共方法
public function send_post($url, $post_data) {
$postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $postdata,
'timeout' => 15 * 60 // 超时时间(单位:s)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
创建围栏
//创建圆形围栏
public function createCircle($name, $desc,$key,$sid,$center,$radius)
{
$url = 'https://tsapi.amap.com/v1/track/geofence/add/circle';
$arr = [
'name' => $name,//每一个围栏的名称不能相同
'desc' => $desc,//每一个围栏的描述不能相同
'key' => $key,
'sid' => $sid,
'center' => $center,//格式如x,y--经度在前纬度在后
'radius' => $radius,//单位:米,整数,最小1最大50000
];
$res = $this->send_post($url, $arr);//gfid围栏的唯一标识,务必保存
print_r($res);exit;
}
//创建多边形围栏
public function createPolygon($name, $desc, $points,$key,$sid)
{
$url = 'https://tsapi.amap.com/v1/track/geofence/add/polygon';
$arr['key'] = $key;
$arr['sid'] = $sid;
$arr['name'] = $name;
$arr['desc'] = $desc;
$arr['points'] = $points;//经度1,纬度1;经度2,纬度2;|||注意:经纬度之间用英文逗号分割,不同的点之间用英文分号分割
//且这些点组成的最大面积必须小于100平方公里(是面积不是距离),若想大于100平方公里请找高德客服
//points点的顺序必须是顺时针或者是逆时针,例:矩形的情况下第二个点不可为第一个点的对角点
//points最少传三个最多传100
$res = $this->send_post($url, $arr);//gfid围栏的唯一标识,务必保存
print_r($res);exit;
}
//线行围栏:就是一条直线,允许在直线上左右偏差1-300米
//行政区围栏:根据行政区划编码进行区域划分
查询围栏
public function geofenceList($arr)
{
$url = 'https://tsapi.amap.com/v1/track/geofence/list?key=' . $arr['key'] . '&sid=' . $arr['sid'];//不传gfids分页返回所有的围栏传了就返回gfids包含的围栏
$res = file_get_contents($url);
return json_decode($res, true);
}
删除围栏
public function delGeoFence($gfids,$arr)
{
$url = 'https://tsapi.amap.com/v1/track/geofence/delete';
$arr['key'] = 'web服务key';
$arr['sid'] = '对应的sid';
$arr['gfids'] = $gfids;//可以传多个,以英文逗号分割,最大为100--如果需全部删除,传#all删除所有的
$res = $this->send_post($url, $arr);//删除A成功了就会返回A
return json_decode($res, true);
}
查询指定坐标和围栏的关系
public function locationStatus($location, $gfids)
{
//gfids如果传了就只判断传入的值,可以传多个,以英文逗号分割
//如果不传就判断与传入sid下所有围栏的关系
$arr['key'] = '4f61f40afc5f0af9e42fcb7290209d5a';
$arr['sid'] = '1008773';
$url = 'https://tsapi.amap.com/v1/track/geofence/status/location?key=' . $arr['key'] . '&sid=' . $arr['sid'] . '&location=' . $location . '&gfids=' . $gfids;
$res = file_get_contents($url);//data-results-in 0=不在1=在
return json_decode($res, true);
}
js部分(fastadmin为例,前端纯小白,仅供参考)
<script src="/assets/js/jquery.min.js"></script>
<script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
<script type="text/javascript"
src="https://webapi.amap.com/maps?v=1.4.15&key=jsapi---key&plugin=AMap.Geocoder,AMap.MouseTool"></script>
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: 'jsapikey对应的安全密钥,申请完jsapikey之后就能看到',
}
</script>
<script type="text/javascript">
// 表单提交
$('#submit').click(() => {
$.ajax({
url: '/admin.php/road/road/add',
type: 'post',
dataType: 'json',
data: $('form').serialize(),
success: res => {
console.log(res.code)
if (res.code == 1) {
window.close();
Fast.api.close();
location.href = '/admin.php/road.road/index'
window.parent.location.reload();
}
}
})
return false
})
// var nodeData = {:json_encode($treeList); };
//一、初始化 "地图中心"
var lon = "{$row.lon}" ? "{$row.lon}" : 116.397413;
var lat = "{$row.lat}" ? "{$row.lat}" : 39.920912;
//二、初始地图中心点
var map1 = new AMap.Map("container", {
center: [lon, lat],
resizeEnable: true,
zoom: 10
});
//二、初始地图中心点
var map2 = new AMap.Map("container2", {
center: [lon, lat],
resizeEnable: true,
zoom: 10
});
let mouseTool1 = new AMap.MouseTool(map1)
mouseTool1.on('draw', event => {
console.log(event.obj.getPath())
let a = event.obj.getPath()
let b = ''
a.forEach((item, index) => {
if (b) {
b = b + ';' + item.lng + ',' + item.lat
} else {
b = item.lng + ',' + item.lat
}
})
$('#map_lat_1').val(b)
mouseTool1.close()
})
// 绘制围栏
$('#map1').click( () => {
mouseTool1.close(true)
mouseTool1.polygon({
strokeColor: "#FF33FF",
strokeOpacity: 1,
strokeWeight: 6,
strokeOpacity: 0.2,
fillColor: '#1791fc',
fillOpacity: 0.4,
// 线样式还支持 'dashed'
strokeStyle: "solid",
// strokeStyle是dashed时有效
// strokeDasharray: [30,10],
})
return false
})
let mouseTool2 = new AMap.MouseTool(map2)
mouseTool2.on('draw', event => {
let a = event.obj.getPath()
let b = ''
a.forEach((item, index) => {
if (b) {
b = b + ';' + item.lng + ',' + item.lat
} else {
b = item.lng + ',' + item.lat
}
})
$('#map_lat_2').val(b)
mouseTool2.close()
})
// 绘制围栏
$('#map2').click( () => {
mouseTool2.close(true)
mouseTool2.polygon({
strokeColor: "#FF33FF",
strokeOpacity: 1,
strokeWeight: 6,
strokeOpacity: 0.2,
fillColor: '#1791fc',
fillOpacity: 0.4,
// 线样式还支持 'dashed'
strokeStyle: "solid",
// strokeStyle是dashed时有效
// strokeDasharray: [30,10],
})
return false
})
</script>
html部分,fastadmin为例,仅供参考
<form id="add-form" class="form-horizontal" role="form" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('起点所在位置')}:</label>
<button class="btn" id="map1">绘制围栏</button>
<input type="text" id="map_lat_1" name="row[lng_lat_1]">
<div class="col-xs-12 col-sm-12" id="map_box">
<div id="container"></div>
<div class="input-card hidden" id="map_box_1">
<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">经纬度</span></div>
<input id='lnglat' data-rule="required" type="text" value="">
</div>
<!--<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">地址</span></div>
<input id='address' data-rule="required" type="text" readonly value="">
</div>
<div>
<input id="regeo" type="button" class="btn describe" value="经纬度 -> 地址">
</div>-->
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('终点所在位置')}:</label>
<button class="btn" id="map2">绘制围栏</button>
<input type="text" id="map_lat_2" name="row[lng_lat_2]">
<div class="col-xs-12 col-sm-12" id="map_box2">
<div id="container2"></div>
<div class="input-card hidden" id="map_box_2">
<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">经纬度</span></div>
<input id='lnglat2' data-rule="required" type="text" value="">
</div>
<!--<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">地址</span></div>
<input id='address' data-rule="required" type="text" readonly value="" name="row[address]">
</div>
<div>
<input id="regeo" type="button" class="btn describe" value="经纬度 -> 地址">
</div>-->
</div>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="button" id="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
<link rel="stylesheet" href="/assets/css/amap.css"/>
<style>
#map_box #container {
width: 100%;
height: 580px;
}
.describe {
width: 10rem;
margin-left: 3.8rem;
display: inline;
}
.amap-icon img {
width: 25px;
height: 34px;
}
.amap-marker-label {
border: 0;
background-color: transparent;
}
#map_box {
position: relative !important;
}
#map_box_1 {
position: absolute !important;
width: 28rem;
}
#map_box2 #container2 {
width: 100%;
height: 580px;
}
#map_box2 .input-card {
display: flex;
flex-direction: column;
min-width: 0px;
overflow-wrap: break-word;
background-color: rgb(255, 255, 255);
background-clip: border-box;
width: 22rem;
border-width: 0px;
border-radius: 0.4rem;
box-shadow: rgb(114 124 245 / 50%) 0px 2px 6px 0px;
/*position: fixed;*/
bottom: 1rem;
right: 1rem;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
position: absolute !important;
</style>
