【高德地图API】JS高德地图API实现多边形绘画,高德获取多边形提交数据

目录

  • 前言
  • 效果
  • 实现
    • 引入js
  • 在项目中使用
    • 效果图
    • 引入
    • html
    • CSS
    • 具体实现JS
    • 调用说明
      • 添加的时候
      • 修改的时候
      • 判断是否在范围内
  • java绘画和判断是否在范围内
    • 方式一
    • 方式二
      • pom.xml依赖引入
      • import引入
      • 实现

前言

高德地图官方API:https://lbs.amap.com/demo/javascript-api/example/overlayers/polygon-draw-and-edit
高德地图API版本:1.4.15
使用JS实现高德地图多边形围栏设置(除了简单的例子,还附带本人在项目中的实现)

效果

【高德地图API】JS高德地图API实现多边形绘画,高德获取多边形提交数据_第1张图片

实现

引入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>

在项目中使用

效果图

【高德地图API】JS高德地图API实现多边形绘画,高德获取多边形提交数据_第2张图片

这是本人在项目中的使用(复制粘贴可用)

引入

记得把安全密钥和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">
	
	<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 = '
  • + poi.location.lng + ', ' + poi.location.lat + ')">'; var index = i + 1; if (index == 1) { s += ' ' + index + '' + poi.name; } else if (index == 2) { s += ' ' + index + '' + poi.name; } else if (index == 3) { s += ' ' + index + '' + poi.name; } else { s += ' ' + index + '' + poi.name; } s += ' (' + poi.address + ')'; s += '
  • '
    ; $(".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 = "
    " + e.target.content + "
    "
    ; // 要显示的内容 content += "" 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.apigroupId>
    	<artifactId>amap-java-sdkartifactId>
    	<version>1.4.0version>
    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

    你可能感兴趣的:(地图API,前端插件效果,前端,javascript,高德地图API,html5)