【高德地图API】JS高德地图API实现多边形绘画,高德获取多边形提交数据
目录
前言
高德地图官方API:https://lbs.amap.com/demo/javascript-api/example/overlayers/polygon-draw-and-edit
高德地图API版本:1.4.15
使用JS实现高德地图多边形围栏设置(除了简单的例子,还附带本人在项目中的实现)
效果
实现
引入js
需要添加安全密钥和key,之所以要使用安全密钥是官方在2021-12-02的时候改的,原本只需要key即可的
参考网址:https://lbs.amap.com/api/javascript-api/guide/abc/prepare
这里plugin=AMap.*****是自己需要到的对象
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode:'bf5ed*********************886', // 安全密钥(正式项目官方推荐使用nginx代理方式引入密钥)
}
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=22d1******************b8&plugin=AMap.Autocomplete,AMap.PlaceSearch,AMap.PolyEditor,AMap.Marker"></script>
html实现
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<style>
html,
body,
#container {
width: 100%;
height: 100%;
}
</style>
<title>多边形的绘制和编辑</title>
<link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode:'bf5******************886',
}
</script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=22d******************a20b8&plugin=AMap.PolyEditor"></script>
</head>
<body>
<div id="container"></div>
<div class="input-card" style="width: 120px">
<button class="btn" onclick="startEdit()" style="margin-bottom: 5px">开始编辑</button>
<button class="btn" onclick="submitMap()">结束编辑</button>
</div>
<script type="text/javascript">
var temp_lnglat = []; // 临时存储位置
var tempMap = {}; // 临时存储地图对象
// 要绘画位置的经纬度
var lngLat = [116.400274, 39.905812];
initMap(lngLat);
/**
* ---------------------------------------------------------------------------------------------------------------
* 初始化地图
*/
function initMap(lngLat){
tempMap.map = new AMap.Map("container", {
center: lngLat,
zoom: 14
});
createPolygon(lngLat);
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 创建多边形
* @param {Object} paths
*/
function createPolygon(lngLat, paths){
// 绘画多边形的各个角的经纬度(如果没有就使用这个,在当前位置上创建默认的多边形)
if(!paths || paths.length < 1){
paths = [
[lngLat[0] + 0.003048, lngLat[1] + 0.014442],
[lngLat[0] + 0.010429, lngLat[1] - 0.008257],
[lngLat[0] + 0.002018, lngLat[1] - 0.013458],
[lngLat[0] - 0.010427, lngLat[1] - 0.014446]
]
}
// 赋值给临时数组(提交的时候要这些多边形角的经纬度)
temp_lnglat = paths;
// 创建绘画
var polygon = new AMap.Polygon({
path: paths,
strokeColor: "#0f79d7",
strokeWeight: 3,
strokeOpacity: 0.6,
fillOpacity: 0.4,
fillColor: '#1791fc',
zIndex: 50,
})
tempMap.map.add(polygon)
// 缩放地图到合适的视野级别
tempMap.map.setFitView([polygon])
// 编辑绘画对象
tempMap.polyEditor = new AMap.PolyEditor(tempMap.map, polygon)
// 事件
tempMap.polyEditor.on('addnode', function(event) {
console.log('触发事件:addnode ------------------------------------------')
console.log("添加:", event)
console.log("添加-经度:", event.lnglat.lng, "纬度:", event.lnglat.lat)
})
tempMap.polyEditor.on('adjust', function(event) {
console.log('触发事件:adjust ------------------------------------------')
console.log("修改:", event)
console.log("修改-经度:", event.lnglat.lng, "纬度:", event.lnglat.lat)
})
tempMap.polyEditor.on('removenode', function(event) {
console.log('触发事件:removenode ------------------------------------------')
console.log("removenode:", event)
})
tempMap.polyEditor.on('end', function(event) {
console.log('触发事件: end ------------------------------------------')
console.log("end:", event)
// event.target 即为编辑后的多边形对象
})
}
/**
* ---------------------------------------------------------------------------------------------------------
* 清除绘画
*/
function clearMap() {
tempMap.map.clearMap(tempMap.polyEditor)
tempMap.map.remove(tempMap.polyEditor)
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 开始编辑
*/
function startEdit(){
// 打开编辑
tempMap.polyEditor.open();
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 提交经纬度
*/
function submitMap() {
// 关闭绘画
//tempMap.polyEditor.close();
// 获取所有的经纬度
if(tempMap.polyEditor.bu){
temp_lnglat = tempMap.polyEditor.bu[0];
}
// 去除Q和R属性值,保留lng和lat的值
temp_lnglat = temp_lnglat.map(function(item, index){
return [item.lng, item.lat];
})
console.log("获取所有坐标:", JSON.stringify(temp_lnglat));
}
</script>
</body>
</html>
html搜索提示
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>输入提示</title>
<link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
<style>
html,
body,
#container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="container"></div>
<div class="info">
<div class="input-item">
<div class="input-item-prepend">
<span class="input-item-text" style="width:8rem;">请输入关键字</span>
</div>
<input id='tipinput' type="text">
</div>
</div>
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode:'bf5********************886',
}
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=22d********************0b8&plugin=AMap.Autocomplete,AMap.PlaceSearch"></script>
<script type="text/javascript">
/**
* ---------------------------------------------------------------------------------------------------------
* 渲染地图
*/
function initMap(){
var map = new AMap.Map('container', {
resizeEnable: true, //是否监控地图容器尺寸变化
});
// 输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
// 构造地点查询类
var placeSearch = new AMap.PlaceSearch({
map: map
});
// 注册监听,当选中某条记录时会触发
AMap.event.addListener(auto, "select", selectSearch);
function selectSearch(e) {
console.log(e)
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); // 关键字查询查询
}
}
initMap();
</script>
</body>
</html>
在项目中使用
效果图
这是本人在项目中的使用(复制粘贴可用)
引入
记得把安全密钥和key改了
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode:'bf5e**********************886',
}
</script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=22d**********************20b8&plugin=AMap.Autocomplete,AMap.PlaceSearch,AMap.PolyEditor,AMap.Marker"></script>
html
这里使用layui框架的,所有直接复制过来了,只取关键即可
<div class="layui-form-item">
<label class="layui-form-label">项目地址</label>
<div class="layui-input-block" style="width: 500px;">
<input type="text" name="addr" id="addr" placeholder="输入地址后选择详细,再操作地图"autocomplete="off" class="layui-input">
<div class="lay-search-content">
<ul></ul>
</div>
</div>
</div>
<div class="layui-form-item">
<!-- map地图 -->
<div class="container" id="container" style="height: 500px;width: 750px;"></div>
</div>
CSS
自己写的效果
.lay-search-content{
padding: 10px;
background: white;
border-radius: 4px;
color: #333333;
line-height: 15px;
box-shadow: #00000024 0px 2px 5px 0;
max-height: 300px;
overflow: auto;
display: none;
position: absolute;z-index: 99999;
width: 99%;
}
.lay-search-content li{
list-style: none;
margin: 5px 0px;
padding: 8px 0px;
border-bottom: 1px solid whitesmoke;
cursor: pointer;
}
.lay-search-content li:hover{
background: #f1f1f1;
}
.lay-search-mark{
width: 16px;
display: inline-block;
height: 16px;
background: #c1c1c1;
text-align: center;
line-height: 16px;
border-radius: 50%;
margin-right: 4px;
color: white;
font-size: 12px;
position: relative;
top: -1px;
}
具体实现JS
var temp_lnglat = [116.400274, 39.905812]; // 临时存储当前位置
var temp_fence_lnglat = []; // 临时存储所有位置
var tempMap = {}; // 临时存储地图对象
/**
* ---------------------------------------------------------------------------------------------------------
* 重置地图值
*/
function clearMap(state) {
if(!state){ // 修改的话不赋值
temp_lnglat = [116.400274, 39.905812];
temp_fence_lnglat = [];
}
if(tempMap.polyEditor){
tempMap.map.clearMap(tempMap.polyEditor)
tempMap.map.remove(tempMap.polyEditor)
}
}
/**
* ---------------------------------------------------------------------------------------------------------
* 渲染地图
*/
function initMap(state){
tempMap.map = new AMap.Map('container', {
resizeEnable: true, //是否监控地图容器尺寸变化
center: temp_lnglat,
zoom: 14,
});
// 构造地点查询类
tempMap.placeSearch = new AMap.PlaceSearch({
city: "全国", // 兴趣点城市
});
$("#addr").bind('input propertychange', function() {
var text = $("#addr").val();
searchAddr(text)
})
clickPosition(temp_lnglat[0], temp_lnglat[1], state);
}
/**
* --------------------------------------------------------------------------------------------------------------------
* 地图搜索
* @return
*/
function searchAddr(text) {
// 关键字查询,设置成输入框input就好了,下面返回的集合中有name,可以自己重新查询结果选择
tempMap.placeSearch.search(text, function (status, result) {
// 查询成功时,result即对应匹配的POI信息
console.log("搜索结果坐标:", result)
if (!result.poiList){
return;
}
var pois = result.poiList.pois;
$(".lay-search-content").css("display", "block");
$(".lay-search-content>ul").empty();
for (var i = 0; i < pois.length; i++) {
var poi = pois[i];
var s = '<li οnclick="clickPosition(' + poi.location.lng + ', ' + poi.location.lat + ')">';
var index = i + 1;
if (index == 1) {
s += ' <span class="lay-search-mark" style="background: #ff8e63;">' + index + '</span>' + poi.name;
} else if (index == 2) {
s += ' <span class="lay-search-mark" style="background: #edd07d;">' + index + '</span>' + poi.name;
} else if (index == 3) {
s += ' <span class="lay-search-mark" style="background: #cddb82;">' + index + '</span>' + poi.name;
} else {
s += ' <span class="lay-search-mark">' + index + '</span>' + poi.name;
}
s += ' <span style="color: #999;font-size: 12px">(' + poi.address + ')</span>';
s += '</li>';
$(".lay-search-content>ul").append(s);
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
offset: new AMap.Pixel(0, -20),// 相对于基点的偏移位置
title: poi.name
});
// [点标上面显示内容信息]
var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30)});// 地图位置对象
// 点击弹出内容
marker[i].content = poi.name;
marker[i].on('click', markerClick);
function markerClick(e) {
var position = e.target.getPosition();
var content = "<div>" + e.target.content + "</div>"; // 要显示的内容
content += "<div style='text-align: center'><a class='layui-btn layui-btn-sm' οnclick='clickPosition(" + position.lng + ", " + position.lat + ")'>选择设置围栏</a></div>"
infoWindow.setContent(content);
infoWindow.open(tempMap.map, position);
}
// 将创建的点标记添加到已有的地图实例:
tempMap.map.add(marker[i]);
}
tempMap.map.setFitView();
})
}
/**
* --------------------------------------------------------------------------------------------------------------------
* 搜索结果选择设置围栏
* @param lng
* @param lat
*/
function clickPosition(lng, lat, state) {
$(".lay-search-content").css("display", "none");
clearMap(state);
temp_lnglat = [lng, lat];
// 添加点标
var markers = new AMap.Marker({
position: temp_lnglat, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
offset: new AMap.Pixel(0, -20),// 相对于基点的偏移位置
});
tempMap.map.add(markers);
tempMap.map.setCenter(temp_lnglat)
createPolygon(temp_lnglat, temp_fence_lnglat);
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 创建多边形
* @param {Object} paths
*/
function createPolygon(lngLat, paths){
// 绘画多边形的各个角的经纬度(如果没有就使用这个,在当前位置上创建默认的多边形)
if(!paths || paths.length < 1){
paths = [
[lngLat[0] + 0.003048, lngLat[1] + 0.014442],
[lngLat[0] + 0.010429, lngLat[1] - 0.008257],
[lngLat[0] + 0.002018, lngLat[1] - 0.013458],
[lngLat[0] - 0.010427, lngLat[1] - 0.014446]
]
}
// 赋值给临时数组(提交的时候要这些多边形角的经纬度)
temp_fence_lnglat = paths;
// 创建绘画
var polygon = new AMap.Polygon({
path: paths,
strokeColor: "#0f79d7",
strokeWeight: 3,
strokeOpacity: 0.6,
fillOpacity: 0.4,
fillColor: '#1791fc',
zIndex: 50,
})
tempMap.map.add(polygon)
// 缩放地图到合适的视野级别
tempMap.map.setFitView([polygon])
// 编辑绘画对象
tempMap.polyEditor = new AMap.PolyEditor(tempMap.map, polygon)
// 事件
tempMap.polyEditor.on('addnode', function(event) {
console.log('触发事件:addnode ------------------------------------------')
console.log("添加:", event)
console.log("添加-经度:", event.lnglat.lng, "纬度:", event.lnglat.lat)
})
tempMap.polyEditor.on('adjust', function(event) {
console.log('触发事件:adjust ------------------------------------------')
console.log("修改:", event)
console.log("修改-经度:", event.lnglat.lng, "纬度:", event.lnglat.lat)
})
tempMap.polyEditor.on('removenode', function(event) {
console.log('触发事件:removenode ------------------------------------------')
console.log("removenode:", event)
})
tempMap.polyEditor.on('end', function(event) {
console.log('触发事件: end ------------------------------------------')
console.log("end:", event)
// event.target 即为编辑后的多边形对象
})
// 打开编辑
tempMap.polyEditor.open();
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 开始编辑
*/
function startEdit(){
// 打开编辑
tempMap.polyEditor.open();
}
/**
* ---------------------------------------------------------------------------------------------------------------
* 提交经纬度
*/
function submitMap() {
// 关闭绘画
//tempMap.polyEditor.close();
// 获取所有的经纬度
if(tempMap.polyEditor.bu){
temp_fence_lnglat = tempMap.polyEditor.bu[0];
}
// 去除Q和R属性值,保留lng和lat的值
temp_fence_lnglat = temp_fence_lnglat.map(function(item, index){
return [item.lng, item.lat];
})
console.log("获取所有坐标:", JSON.stringify(temp_fence_lnglat));
}
调用说明
基于上面写好的js,直接复制去调用即可
添加的时候
initMap();
修改的时候
data.lngLat和data.fenceLngLat就是我们存储起来已经设置的经纬度
temp_lnglat = JSON.parse(data.lngLat);
temp_fence_lnglat = JSON.parse(data.fenceLngLat);
initMap(true);
判断是否在范围内
参考API:https://lbs.amap.com/demo/javascript-api/example/relationship-judgment/point-surface-relation
// 创建点(显示当前用户的点位)
var marker = new AMap.Marker({
map: map,
position: [116.566298, 40.014179]
});
// 判断是否在范围内
var point = marker.getPosition();
var isPointInRing = AMap.GeometryUtil.isPointInRing(point, paths); // paths 就是多边形的那些坐标数组
console.log("是否在范围内:", isPointInRing?'是':'否')
java绘画和判断是否在范围内
方式一
参考网址1:https://blog.csdn.net/qq_39190679/article/details/102524601
参考网址2:https://www.jianshu.com/p/5a2398a84889
参考网址3:https://zhuanlan.zhihu.com/p/534997829
package cn.geesuntar.utils;
import com.alibaba.fastjson.JSONArray;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
public class RegionUtil {
private static double EARTH_RADIUS = 6378137;
private static double rad(double d) {
return d * Math.PI / 180.0;
}
/**
* 多边形
* @param point 要判断的点的横纵坐标
* @param polygon 组成的顶点坐标集合
* @return
*/
public static boolean isInPolygon(Point2D.Double point, List<Point2D.Double> polygon) {
java.awt.geom.GeneralPath peneralPath = new java.awt.geom.GeneralPath();
Point2D.Double first = polygon.get(0);
peneralPath.moveTo(first.x, first.y);
polygon.remove(0);
for (Point2D.Double d : polygon) {
peneralPath.lineTo(d.x, d.y);
}
peneralPath.lineTo(first.x, first.y);
peneralPath.closePath();
return peneralPath.contains(point);
}
/**
* 通过经纬度获取距离(单位:米)
*
* @param lat1 纬度1
* @param lng1 经度1
* @param lat2 纬度2
* @param lng2 经度2
* @return 距离
*/
public static double getDistance(double lat1, double lng1, double lat2,
double lng2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 10000d) / 10000d;
return s;
}
/**
* 圆形
* @param lat1 纬度
* @param lat2 经度
* @param lng1 纬度
* @param lng2 经度
* @param radius 判断一个点是否在圆形区域内,比较坐标点与圆心的距离是否小于半径
*/
public static boolean isInCircle(double lng1, double lat1, double lng2, double lat2, double radius) {
double distance = getDistance(lat1, lng1, lat2, lng2);
System.out.println("半径:"+radius+"解析半径:"+distance);
if (distance > radius) {
return false;
} else {
return true;
}
}
public static void main(String[] args) {
String str = "[[114.125986,22.607612],[114.125241,22.607122],[114.125547,22.606775],[114.126303,22.607236]]";
JSONArray jsonArray = JSONArray.parseArray(str);
JSONArray jsonArray1 = null;
List<Point2D.Double> polygon = new ArrayList<>();
for (Object o : jsonArray) {
jsonArray1 = JSONArray.parseArray(o.toString());
polygon.add(new Point2D.Double(jsonArray1.getDouble(0),jsonArray1.getDouble(1)));
}
System.out.println(RegionUtil.isInPolygon(new Point2D.Double(114.125872,22.606983), polygon));
}
}
方式二
参考网址1:https://www.php.cn/faq/584994.html
参考网址2:https://blog.51cto.com/u_16175486/6825616
pom.xml依赖引入
<dependency>
<groupId>com.amap.api</groupId>
<artifactId>amap-java-sdk</artifactId>
<version>1.4.0</version>
</dependency>
import引入
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
实现
创建一个地图视图对象,并将其添加到布局中
MapView mapView = new MapView(context, new AMapOptions());
//layout.addView(mapView);
初始化地图
AMap aMap = mapView.getMap();
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.90923, 116.397428), 10));
这里我们就可以将设置的多边形各个点添加到集合里
List<LatLng> points = new ArrayList<>();
points.add(new LatLng(39.910698, 116.399406));
points.add(new LatLng(39.909819, 116.405778));
points.add(new LatLng(39.919719, 116.405814));
points.add(new LatLng(39.919657, 116.399362));
设置多边形的绘画
PolygonOptions polygonOptions = new PolygonOptions();
polygonOptions.addAll(points);
polygonOptions.strokeColor(Color.RED);
polygonOptions.fillColor(Color.argb(50, 255, 0, 0));
polygonOptions.strokeWidth(10);
将多边形添加到地图中
Polygon polygon = aMap.addPolygon(polygonOptions);
这里就是判断用户的点是否在我们设置的多边形范围内
LatLng location = new LatLng(39.913678, 116.403873);
boolean contains = polygon.contains(location);
System.out.println("该位置是否在多边形内:" + contains);
所应用的功能大概就是这样啦!
圆形围栏可参考:https://blog.csdn.net/weixin_43992507/article/details/130731955