这里用的高德地图.
先说思路:jsp页面展示点线面的坐标,点,线,面,新增,修改,展示,给每个图形绑定左右键事件,都在一个页面上了.把数据放到数据库.
有几点要注意的:
1,在新增和修改坐标的时候因为用的是高德地图,所以获取的是高德坐标-GCJ02形式,但是为了可扩展性,需要转成通用坐标-WGS84
存储到数据库,方便日后在高德和百度地图之间来回折腾,至少以后不用动数据库了.
2,高德地图是支持直接获取到geometry格式的数据的(别问geometry是啥,百度去!),为了以后能用mysql的空间查询.所以前端获取到geo的时候需要转成geojson,这样才能平平安安的传到controller里去.
3,geometry是对象格式.但是在数据库中建的是个字段.在controller里需要用到转换器,把geojson再转成geometry格式,并放到相应的实体类对象的属性中.
4,mymatis不知道这是啥,需要写个工具类让mybatis知道这个类型是可以放到数据库中geometry类型的字段中的.
下面代码:
jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ include file="/common.jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="${rootpath}/static/jquery.min.js"></script>
<script src="${rootpath}/static/gcoord.js"></script>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>显示多个多边形用geo传递</title>
<link rel="stylesheet"
href="https://cache.amap.com/lbs/static/main1119.css"/>
<script
src="https://webapi.amap.com/maps?v=1.4.6&key=自己申请吧&plugin=AMap.PolyEditor,AMap.MouseTool"></script>
<script type="text/javascript"
src="https://cache.amap.com/lbs/static/addToolbar.js"></script>
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
</head>
<body>
<div id="container"></div>
<div class="button-group">
<input type="button" class="button" value="鼠标绘制点" id="point"/>
<input type="button" class="button" value="鼠标绘制线" id="line"/>
<input type="button" class="button" value="鼠标绘制面" id="polygon"/>
<%-- <input type="button" class="button" value="开始编辑" onClick="openPolygon()"/>
<input type="button" class="button" value="结束编辑" onClick="editor.closeEditPolygon()"/>--%>
<input type="button" value="保存图层" onclick="save()"/>
</div>
<script>
function geoBindClick(geo) {//提取的绑定事件方法
geo.on('click', (data) => {//绑定左键事件
if(!mouseTool.drawType){//在画图状态下
if (editor._Editor) {//如果有编辑的图形
editor._Editor.close();//关闭其他编辑的图形
editor._Editor = null;
}
editor._Editor = new AMap.PolyEditor(map, data.target);//创建当前图形编辑对象,打开当前图形编辑
editor._Editor.open();
}
});
geo.on('rightclick', (data) => {//绑定右键事件
if(!mouseTool.drawType){
alert("rid为" + data.target.getExtData().id);//右键点击提示信息
}
});
}
var edit;
var editorTool, map = new AMap.Map("container", {
resizeEnable: true,
center: [116.41714, 39.934081],//地图中心点
zoom: 13 //地图显示的缩放级别
});
var arr1 = [];//过程中用到的数组
arr1 =${list};//获取后台传过来的list
console.log(arr1);
var arr = gcoord.transform(arr1, gcoord.WGS84, gcoord.GCJ02);//将国标转成高德坐标
//遍历geojson对象含,点,线,面
for (var i = 0; i < arr.features.length; i++) {
var editor = {};
if (arr.features[i].geometry.type == 'Polygon') {//如果是多变形对象
var polygonArr = new Array();//创建多边形坐标数组
polygonArr.push(arr.features[i].geometry.coordinates[0]);
console.log(polygonArr);
var polygon = new AMap.Polygon({
path: polygonArr,//设置多边形边界路径 polygon[i]
strokeColor: "#FF33FF", //线颜色
strokeOpacity: 0.2, //线透明度
strokeWeight: 3, //线宽
fillColor: "#1791fc", //填充色
fillOpacity: 0.35,//填充透明度
extData: (arr.features[i].properties)//给每个面放进自定义的数据
});
console.log(polygon);
polygon.setMap(map);
//获取鼠标点击
geoBindClick(polygon);
}
else if (arr.features[i].geometry.type == 'LineString') {//如果是线对象
var lineArr = new Array();
lineArr = arr.features[i].geometry.coordinates;
console.log(lineArr);
var polyline = new AMap.Polyline({
path: lineArr, //设置线覆盖物路径
strokeColor: "#3366FF", //线颜色
strokeOpacity: 1, //线透明度
strokeWeight: 5, //线宽
strokeStyle: "solid", //线样式
strokeDasharray: [10, 5], //补充线样式
extData: (arr.features[i].properties)//给每个线放进自定义的数据
});
console.log(polyline);
polyline.setMap(map);
//获取鼠标点击
geoBindClick(polyline);
}
else if (arr.features[i].geometry.type == 'Point') {//如果是点对象
var pointM = new AMap.Marker({
icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png",
position: arr.features[i].geometry.coordinates,
extData: (arr.features[i].properties),//给每个线放进自定义的数据
draggable: false
raiseOnDrag: true*/
});
pointM.setDraggable({draggable: false});
pointM.setMap(map);
geoBindClick(pointM);
}
}
pointM.setMap(map);
function save() {
let result = [];
for (let y = 0; y < this.map.getAllOverlays().length; ++y) {
var val = this.map.getAllOverlays()[y].toGeoJSON();
var gd = gcoord.transform(val, gcoord.GCJ02, gcoord.WGS84);
let len = gd.geometry.coordinates[0].length;
if (gd.geometry.type.indexOf('Polygon') > -1 && gd.geometry.coordinates[0][0][0] !== gd.geometry.coordinates[0][len - 1][0] &&
gd.geometry.coordinates[0][0][1] !== gd.geometry.coordinates[0][len - 1][1]) {
gd.geometry.coordinates[0].push(gd.geometry.coordinates[0][0]);
}
if(this.map.getAllOverlays()[y].getExtData() != null){
gd.properties = this.map.getAllOverlays()[y].getExtData();//添加自定义属性到geometry对象
}
result.push(gd);
}
var geo = gcoord.featureCollection(result);
console.log("111111111111111111111111111111111111111111111");
console.log(gd);
console.log(geo);
$.ajax({
url: '${rootpath}/coorclass',
type: 'post',
data: {
'val': JSON.stringify(geo)
},
success: function (data) {
}
});
}
//在地图中添加MouseTool插件
var mouseTool = new AMap.MouseTool(map);
AMap.event.addListener(mouseTool,"draw",function(e, obj){
geoBindClick(e.obj)//给新画的图形绑定左右键事件
});
AMap.event.addDomListener(document.getElementById('point'), 'click', function() {//画点
mouseTool.close(false);
if(editor._Editor) {//关闭其他图形的编辑状态
editor._Editor.close();
editor._Editor = null;
}
if(!mouseTool.drawType || mouseTool.drawType !== 'point') {
mouseTool.drawType = 'point';
mouseTool.marker({offset: new AMap.Pixel(-14, -11)});
}else {
mouseTool.drawType = null;
}
}, false);
AMap.event.addDomListener(document.getElementById('line'), 'click', function() {//画线
mouseTool.close(false);
if(editor._Editor) {
editor._Editor.close();
editor._Editor = null;
}
if(!mouseTool.drawType || mouseTool.drawType !== 'polyline') {
mouseTool.drawType = 'polyline';
mouseTool.polyline();
}else {
mouseTool.drawType = null;
}
}, false);
AMap.event.addDomListener(document.getElementById('polygon'), 'click', function() {//画面
mouseTool.close(false);
if(editor._Editor) {
editor._Editor.close();
editor._Editor = null;
}
if(!mouseTool.drawType || mouseTool.drawType !== 'polygon'){
mouseTool.drawType = 'polygon';
mouseTool.polygon();
}else {
mouseTool.drawType = null;
}
}, false);
</script>
</body>
</html>
转换工具类:
含geojson转geometry 和 geometry转geojson
package com.bike.park.util;
import cn.hutool.core.date.DateUtil;
import org.locationtech.jts.geom.Geometry;
import org.wololo.geojson.Feature;
import org.wololo.geojson.FeatureCollection;
import org.wololo.geojson.GeoJSON;
import org.wololo.geojson.GeoJSONFactory;
import org.wololo.jts2geojson.GeoJSONReader;
import org.wololo.jts2geojson.GeoJSONWriter;
import com.bike.park.domain.Coor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
public final class GeoUtils{
//json转geometry对象
public static <T extends Object> List<T> geoJsonToBeans(String geoJson , Class<T> instance) throws IOException, IllegalAccessException, InstantiationException {
// InputStream is = new ByteArrayInputStream(geoJson.getBytes());
// org.geotools.feature.FeatureCollection featureCollection = fjson.readFeatureCollection(is);
// org.opengis.feature.Feature[] features = new org.opengis.feature.Feature[featureCollection.size()];
// featureCollection.toArray(features);
GeoJSON geoJSON = GeoJSONFactory.create(geoJson);
Feature[] features = null;
if(geoJSON instanceof Feature){
features = new Feature[1];
features[0] = (Feature)geoJSON;
}else {
FeatureCollection featureCollection = (FeatureCollection)geoJSON;
features = featureCollection.getFeatures();
}
List<T> result = new ArrayList<>(features.length);
Field[] fields = instance.getDeclaredFields();
GeoJSONReader reader = new GeoJSONReader();
for (int i = 0; i < features.length; i++) {
T data = instance.newInstance();
for (Field field : fields) {
field.setAccessible(true);
try {
if (field.getType().equals(Geometry.class)) {
org.wololo.geojson.Geometry geoTemp = features[i].getGeometry();
Geometry geometry = reader.read(geoTemp);
if(null != geometry) {
field.set(data ,geometry);
}
} else if(field.getType().equals(Date.class)) {
Object val = features[i].getProperties().get(field.getName());
if(null != val){
field.set(data, DateUtil.parse(val.toString()));
}
}else if(field.getType().equals(int.class)|| field.getType().equals(Integer.class)) {
Object val = features[i].getProperties().get(field.getName());
if(null != val){
field.set(data, Integer.valueOf(val.toString()));
}
}else if(field.getType().equals(float.class) || field.getType().equals(Float.class)) {
Object val = features[i].getProperties().get(field.getName());
if(null != val){
field.set(data, Float.valueOf(val.toString()));
}
}else {
Object val = features[i].getProperties().get(field.getName());
if(null != val){
field.set(data, val);
}
}
System.out.println(field.getGenericType());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
result.add(data);
}
return result;
}
//geometry对象转json
public static <T extends Object> String beanToGeoJson(T data) throws IllegalAccessException {
List<Feature> features = new ArrayList<>();
if(data instanceof List){
features = beansToFeatrueList((List<?>) data);
}else {
features.add(beanToFeature(data));
}
GeoJSONWriter writer = new GeoJSONWriter();
GeoJSON json = writer.write(features);
return json.toString();
}
private static<T extends Object> Feature beanToFeature(T data) throws IllegalAccessException {
Map<String, Object> properties = new HashMap<>();
Geometry geometry = null;
Field[] fields = data.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object fd = field.get(data);
if(fd instanceof Geometry){
geometry = (Geometry) fd;
}else {
properties.put(field.getName(), field.get(data));
}
}
GeoJSONWriter writer = new GeoJSONWriter();
Feature feature = new Feature(writer.write(geometry), properties);
return feature;
}
private static List<Feature> beansToFeatrueList(List<?> data) throws IllegalAccessException {
List<Feature> featureList = new ArrayList<>();
for (Object datum : data) {
Feature feature = beanToFeature(datum);
featureList.add(feature);
}
return featureList;
}
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException {
// String wkt = "{\n" +
// " \"type\": \"FeatureCollection\",\n" +
// " \"features\": [\n" +
// " {\n" +
// " \"type\": \"Feature\",\n" +
// " \"properties\": {\n" +
// " \"bmapId\": \"feature__3\",\n" +
// " \"name\": \"三角形\",\n" +
// " \"createtime\": \"2018-05-03\",\n" +
// " \"id\": 1\n" +
// " },\n" +
// " \"geometry\": {\n" +
// " \"type\": \"Polygon\",\n" +
// " \"coordinates\": [\n" +
// " [\n" +
// " [\n" +
// " 39.9689,\n" +
// " 116.461105\n" +
// " ],\n" +
// " [\n" +
// " 39.906939,\n" +
// " 116.377742\n" +
// " ],\n" +
// " [\n" +
// " 39.894097,\n" +
// " 116.466279\n" +
// " ],\n" +
// " [\n" +
// " 39.9689,\n" +
// " 116.461105\n" +
// " ]\n" +
// " ]\n" +
// " ]\n" +
// " }\n" +
// " },\n" +
// " {\n" +
// " \"type\": \"Feature\",\n" +
// " \"properties\": {\n" +
// " \"bmapId\": \"feature__4\",\n" +
// " \"name\": \"多边形\",\n" +
// " \"createtime\": \"20180503\",\n" +
// " \"id\": 2\n" +
// " },\n" +
// " \"geometry\": {\n" +
// " \"type\": \"Polygon\",\n" +
// " \"coordinates\": [\n" +
// " [\n" +
// " [\n" +
// " 39.94899,\n" +
// " 116.513422\n" +
// " ],\n" +
// " [\n" +
// " 39.899412,\n" +
// " 116.567464\n" +
// " ],\n" +
// " [\n" +
// " 39.944122,\n" +
// " 116.601384\n" +
// " ],\n" +
// " [\n" +
// " 39.971997,\n" +
// " 116.585862\n" +
// " ],\n" +
// " [\n" +
// " 39.975978,\n" +
// " 116.573788\n" +
// " ],\n" +
// " [\n" +
// " 39.974208,\n" +
// " 116.56229\n" +
// " ],\n" +
// " [\n" +
// " 39.970227,\n" +
// " 116.552517\n" +
// " ],\n" +
// " [\n" +
// " 39.9689,\n" +
// " 116.541018\n" +
// " ],\n" +
// " [\n" +
// " 39.94899,\n" +
// " 116.513422\n" +
// " ]\n" +
// " ]\n" +
// " ]\n" +
// " }\n" +
// " }\n" +
// " ]\n" +
// "}";
//String wkt = "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__1\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[[39.920665,116.466276],[39.897198,116.43983],[39.897198,116.493297]]]]}},{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__2\"},\"geometry\":{\"type\":\"Point\",\"coordinates\":[39.947221,116.469151]}},{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__3\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[[39.955627,116.300704],[39.902511,116.301853],[39.932615,116.328874]]]]}}]}";
//String wkt = "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__1\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[39.9689,116.461105]]]}},{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__2\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[39.94899,116.513422]]]}},{\"type\":\"Feature\",\"properties\":{\"bmapId\":\"feature__3\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[[39.914466,116.567464],[39.97642,116.518597],[39.920221,116.479502]]]]}}]}";
//String wkt = "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[255351.0429,474966.9279],[255529.2966,474272.46]]},\"properties\":{\"gid\":\"123456\",\"direction\":2,\"orientation\":1},\"id\":\"fid-50149944_164d5c515c0_-8000\"},{\"type\":\"Feature\",\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[255529.2966,474272.46],[256166.0583,473979.4492]]},\"properties\":{\"gid\":\"123456\",\"direction\":2,\"orientation\":1},\"id\":\"fid-50149944_164d5c515c0_-7fff\"}]}";
//String wkt = "{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[116.34581543862816,39.9239638666205],[116.34924866616723,39.89038576444518],[116.42168976724145,39.88841006945528],[116.41756989419457,39.92686002969596]]]}}";
String wkt = "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"name\":\"金广通\",\"id\":1},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[39.90764094871865,116.56155784524113],[39.970225890953586,116.51250005513577],[39.91346215335588,116.47360443467369],[39.90764094871865,116.56155784524113]]]}},{\"type\":\"Feature\",\"properties\":{\"name\":\"金广通\",\"id\":2},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[39.90764094871865,116.56155784524113],[39.970225890953586,116.51250005513577],[39.91346215335588,116.47360443467369],[39.90764094871865,116.56155784524113]]}},{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Point\",\"coordinates\":[39.90764094871865,116.56155784524113]}}]}";
List<Coor> geoBeans = GeoUtils.geoJsonToBeans(wkt , Coor.class);
String s = GeoUtils.beanToGeoJson(geoBeans);
String dd = GeoUtils.beanToGeoJson(geoBeans.get(0));
// GeometryCollection geometryCollection = jsonToGeos(wkt);
// String json = geoToJson(wkt,map);
System.out.println(s);
}
}
mybatis的工具类:
package com.bike.park.mybatis.handler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* mybatis类型转换
* @author Administrator
*
*/
@MappedTypes(Geometry.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class GeoToStringTypeHandler implements TypeHandler<Geometry> {
@Override
public void setParameter(PreparedStatement preparedStatement , int i , Geometry geometry , JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, geometry.toString());
}
@Override
public Geometry getResult(ResultSet resultSet , String s) throws SQLException {
String wkt = resultSet.getString(s);
return convertGeo(wkt);
}
@Override
public Geometry getResult(ResultSet resultSet , int i) throws SQLException {
String wkt = resultSet.getString(i);
return convertGeo(wkt);
}
@Override
public Geometry getResult(CallableStatement callableStatement , int i) throws SQLException {
String wkt = callableStatement.getString(i);
return convertGeo(wkt);
}
private Geometry convertGeo(String wkt){
if(null == wkt || wkt.isEmpty()){
return null;
}
WKTReader reader = new WKTReader();
Geometry geometry = null;
try {
geometry = reader.read(wkt);
} catch (ParseException e) {
e.printStackTrace();
}
return geometry;
}
}
这个工具类需要在mybatis配置文件中配下路径,我用的springboot所以比较简单
mybatis.type-handlers-package: com.bike.park.mybatis.handler
xml贴出来看下保险点:
<insert id="insertListCoor" parameterType="java.util.List">
REPLACE into test_coor
(
id,
coor,
name,
address,
information,
remark,
geo
)
values
<foreach collection="list" item="item" index="index"
separator=",">
(
#{item.id},
#{item.coor},
#{item.name},
#{item.address},
#{item.information},
#{item.remark},
GeomFromText(#{item.geo})
)
</foreach>
</insert>
有几个关键字必须要用,至于为什么去查百度吧~!
依赖:
<!--json - geo转换 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.3</version>
</dependency>
<dependency>
<groupId>org.wololo</groupId>
<artifactId>jts2geojson</artifactId>
<version>0.12.0</version>
</dependency>
<!--json-lib-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
左键修改,点谁谁进入修改,右键点击弹框显示本图形信息,每次保存获取地图所有的对象,到数据库,有id的修改,没id新增.