Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~
Java后端進行經(jīng)緯度點抽稀聚合,HTML呈現(xiàn)及前端聚合實現(xiàn)點聚合~
- 1. 效果圖~
- 1.1 前端實現(xiàn)聚合及呈現(xiàn)
- 1.2 后端實現(xiàn)點聚合,前端渲染呈現(xiàn)效果圖
- 2. 原理
- 3. 源碼
- 3.1 前端JS實現(xiàn)點聚合及呈現(xiàn)源碼
- 3.2 后端點聚合(返回geojson)及前端自實現(xiàn)渲染源碼
- 參考
1. 效果圖~
1.1 前端實現(xiàn)聚合及呈現(xiàn)
1.2 后端實現(xiàn)點聚合,前端渲染呈現(xiàn)效果圖
2. 原理
- 構(gòu)建測試數(shù)據(jù)
- 依賴前端傳遞的參數(shù):bounds、mPXInMeters、zoom;分別是窗口的可視經(jīng)緯度范圍、單位像素距離、地圖級別;
單位像素距離也可以根據(jù)地圖級別進行計算;
{“l(fā)evel”: 0, “resolution”: 156543.033928},
{“l(fā)evel”: 1, “resolution”: 78271.5169639999},
{“l(fā)evel”: 2, “resolution”: 39135.7584820001},
{“l(fā)evel”: 3, “resolution”: 19567.8792409999},
{“l(fā)evel”: 4, “resolution”: 9783.93962049996},
{“l(fā)evel”: 5, “resolution”: 4891.96981024998},
{“l(fā)evel”: 6, “resolution”: 2445.98490512499},
{“l(fā)evel”: 7, “resolution”: 1222.99245256249},
{“l(fā)evel”: 8, “resolution”: 611.49622628138},
{“l(fā)evel”: 9, “resolution”: 305.748113140558},
{“l(fā)evel”: 10, “resolution”: 152.874056570411},
{“l(fā)evel”: 11, “resolution”: 76.4370282850732},
{“l(fā)evel”: 12, “resolution”: 38.2185141425366},
{“l(fā)evel”: 13, “resolution”: 19.1092570712683},
{“l(fā)evel”: 14, “resolution”: 9.55462853563415},
{“l(fā)evel”: 15, “resolution”: 4.77731426794937},
{“l(fā)evel”: 16, “resolution”: 2.38865713397468},
{“l(fā)evel”: 17, “resolution”: 1.19432856685505},
{“l(fā)evel”: 18, “resolution”: 0.597164283559817}
- 后端可以設(shè)置多少個像素聚合;
3. 源碼
3.1 前端JS實現(xiàn)點聚合及呈現(xiàn)源碼
<!DOCTYPE html>
<html>
<head><meta charset='utf-8' /><title>創(chuàng)建樣式聚類</title><meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /><script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.js'></script><link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css' rel='stylesheet' /><style>body { margin:0; padding:0; }#map { position:absolute; top:0; bottom:0; width:100%; }</style>
</head>
<body><div id='map'></div><script>
mapboxgl.accessToken = 'pk.eyJ1IjoiemhhbmcyMDIxIiwiYSI6ImNrbGthdmFvbDM0cTMyb3M2eXFiODR5d3QifQ.ow97I1ikb9zlP3p9qmFuBQ';
var map = new mapboxgl.Map({container: 'map',style: 'mapbox://styles/mapbox/dark-v10',center: [-103.59179687498357, 40.66995747013945],zoom: 3
});map.on('load', function() {// Add a new source from our GeoJSON data and set the// 'cluster' option to true. GL-JS will add the point_count property to your source data.map.addSource("earthquakes", {type: "geojson",// Point to GeoJSON data. This example visualizes all M1.0+ earthquakes// from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program.data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",cluster: true,clusterMaxZoom: 14, // Max zoom to cluster points onclusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)});map.addLayer({id: "clusters",type: "circle",source: "earthquakes",filter: ["has", "point_count"],paint: {// Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)// with three steps to implement three types of circles:// * Blue, 20px circles when point count is less than 100// * Yellow, 30px circles when point count is between 100 and 750// * Pink, 40px circles when point count is greater than or equal to 750"circle-color": ["step",["get", "point_count"],"#51bbd6",100,"#f1f075",750,"#f28cb1"],"circle-radius": ["step",["get", "point_count"],20,100,30,750,40]}});map.addLayer({id: "cluster-count",type: "symbol",source: "earthquakes",filter: ["has", "point_count"],layout: {"text-field": "{point_count_abbreviated}","text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],"text-size": 12}});map.addLayer({id: "unclustered-point",type: "circle",source: "earthquakes",filter: ["!", ["has", "point_count"]],paint: {"circle-color": "#11b4da","circle-radius": 4,"circle-stroke-width": 1,"circle-stroke-color": "#fff"}});// inspect a cluster on clickmap.on('click', 'clusters', function (e) {var features = map.queryRenderedFeatures(e.point, { layers: ['clusters'] });var clusterId = features[0].properties.cluster_id;map.getSource('earthquakes').getClusterExpansionZoom(clusterId, function (err, zoom) {if (err)return;map.easeTo({center: features[0].geometry.coordinates,zoom: zoom});});});map.on('mouseenter', 'clusters', function () {map.getCanvas().style.cursor = 'pointer';});map.on('mouseleave', 'clusters', function () {map.getCanvas().style.cursor = '';});
});
</script></body>
</html>
3.2 后端點聚合(返回geojson)及前端自實現(xiàn)渲染源碼
/*** @param visibleBounds 屏幕的范圍 前端傳* @param list 所有的點數(shù)據(jù)* @param mClusters 聚合后的數(shù)據(jù)集合* @param isLattice 是否是方格和距離的算法 , 是 方格和距離的算法 , 否 距離算法* @return*/
private static void calculateOrgClusters(LatLngBounds visibleBounds, List<Map<String, Object>> list, List<Cluster> mClusters, double mClusterDistance, Integer zoom, boolean isLattice) {mIsCanceled = false;mClusters.clear();ClusterItem clusterItem = new RegionItem();LatLng mLatLng;for (int i = 0; i < list.size(); i++) {Map<String, Object> data = list.get(i);mLatLng = new LatLng(Double.parseDouble(data.get("lat").toString()), Double.parseDouble(data.get("lng").toString()));clusterItem = new RegionItem(mLatLng, data);if (mIsCanceled) {return;}LatLng latlng = clusterItem.getPosition();if (visibleBounds.contains(latlng)) {Cluster cluster = null;if (isLattice) {// 方格和距離的算法cluster = getClusterFangGe(latlng, mClusters);} else {// 距離算法cluster = getCluster(latlng, mClusters, mClusterDistance, zoom);}if (cluster != null) {cluster.addCount();} else {cluster = new Cluster(latlng);mClusters.add(cluster);cluster.addClusterItem(clusterItem);cluster.addCount();cluster.setMap(data);// 設(shè)置中心點的范圍if (isLattice) {LatLngBounds latLngBounds = AMapUtils.getAround(latlng, mClusterDistance);cluster.setLatLngBounds(latLngBounds);}}}}
}
<!DOCTYPE html>
<html>
<head><meta charset='utf-8'/><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no'/><!--本地加載的js及css文件--><script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.js'></script><link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css' rel='stylesheet'/><script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><style>#m_infobar {position: absolute;bottom: 100px;left: 20px;width: 200px;height: 200px;overflow: auto;z-index: 201;background: greenyellow;padding-left: 10px;}#menu {background: #fff;position: absolute;z-index: 1;top: 70px;right: 50px;border-radius: 3px;width: 120px;border: 1px solid rgba(0, 0, 0, 0.4);font-family: 'Open Sans', sans-serif;}#menu a {font-size: 13px;color: #404040;display: block;margin: 0;padding: 0;padding: 10px;text-decoration: none;border-bottom: 1px solid rgba(0, 0, 0, 0.25);text-align: center;}#menu a:last-child {border: none;}#menu a:hover {background-color: #f8f8f8;color: #404040;}#menu a.active {background-color: #3887be;color: #ffffff;}#menu a.active:hover {background: #3074a4;}</style>
</head>
<body style="height: 100%;"><div class="panel panel-default"><div class="panel-heading"><div class="row"><div class="col-md-4"><strong>Geojson后端聚合軌跡點</strong></div><div class="col-md-8"><label id="i_click"></label></div></div></div><div class="panel-body"><nav id="menu"></nav><div id="map" style="width: 100%; height: 800px;"><div id='m_infobar'><div id="tooltip-name"></div><div id='tooltip'></div></div></div></div><div class="panel-footer" style="bottom: 0px;"><div class="row"><div class="col-xs-4"><label id="i_coordinate"></label></div><div class="col-xs-8"><label id="i_show"></label></div></div></div>
</div><script>mapboxgl.accessToken = 'pk.eyJ1IjoiemhhbmcyMDIxIiwiYSI6ImNrbGthdmFvbDM0cTMyb3M2eXFiODR5d3QifQ.ow97I1ikb9zlP3p9qmFuBQ';var map = new mapboxgl.Map({resizeEnable: true,container: 'map',style: 'mapbox://styles/mapbox/dark-v10',center: [105, 34],zoom: 4});map.on('load', function () {// Add a new source from our GeoJSON data and set the// 'cluster' option to true. GL-JS will add the mag property to your source data.map.addSource("earthquakes", {type: "geojson",// Point to GeoJSON data. This example visualizes all M1.0+ earthquakes // from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program.// data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",// 只需修改數(shù)據(jù)來源~~data: "/geo?bounds=" + map.getBounds().toString().replaceAll('LngLat', '').replace('Bounds', '').replace('),', ';').replaceAll('(', '').replaceAll(')', '') + "&zoom=" + map.getZoom(),
// cluster: true,// clusterMaxZoom: 20, // Max zoom to cluster points on//clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)});var url = "/geo?bounds=" + map.getBounds().toString().replaceAll('LngLat', '').replace('Bounds', '').replace('),', ';').replaceAll('(', '').replaceAll(')', '') + "&zoom=" + map.getZoom();var zoomOri = map.getZoom();console.log('url------: ' + url);map.addLayer({id: "clusters",type: "circle",source: "earthquakes",filter: ["has", "mag"],paint: {// Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)// with five steps to implement three types of circles:// * 11b4da,1px circles when point mag is 1// * 99CCCC,1px circles when point mag is less than 20// * Blue, 20px circles when point mag is less than 100// * Yellow, 30px circles when point mag is between 100 and 750// * Pink, 40px circles when point mag is greater than or equal to 750"circle-color": ["step",["get", "mag"],"#11b4da",1,"#99CCCC",20,"#3366FF",100,"#f1f075",750,"#f28cb1"],"circle-radius": ["step",["get", "mag"],20,100,30,750,40]}});map.addLayer({id: "cluster-mag",type: "symbol",source: "earthquakes",filter: ["has", "mag"],layout: {"text-field": "{mag}","text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],"text-size": 12}});// inspect a cluster on clickmap.on('click', 'clusters', function (e) {var features = map.queryRenderedFeatures(e.point, {layers: ['clusters']});var deviceId = features[0].properties.deviceId;var clusterId = features[0].properties.clusterId;console.log("deviceId: ", deviceId);console.log("clusterId: ", clusterId);console.log("lng,lat: ", "[" + features[0].geometry.coordinates[0] + "," + features[0].geometry.coordinates[1] + "]");console.log("lng,lat: ", JSON.stringify(features[0].geometry.coordinates));map.easeTo({center: features[0].geometry.coordinates,zoom: map.getZoom()});});map.on("mousemove", function (e) {var features = map.queryRenderedFeatures(e.point, {layers: ["clusters"]});if (features.length) {//show name and value in sidebarvar item = features[0].properties;var arr = [];arr.push("設(shè)備id:" + item.deviceId);arr.push("在線:" + item.online);arr.push("故障:" + item.fault);arr.push("重疊點數(shù):" + item.mag);viewMapOption();document.getElementById('tooltip').innerHTML = arr.join('<br/>');} else {//if not hovering over a feature set tooltip to emptydocument.getElementById('tooltip').innerHTML = "";}});map.on('mouseenter', 'clusters', function () {map.getCanvas().style.cursor = 'pointer';});map.on('mouseleave', 'clusters', function () {map.getCanvas().style.cursor = '';});// 獲取點數(shù)據(jù)function queryData(str) {zoom = map.getZoom();zoom = zoom.toString().substr(0, zoom.toString().indexOf("."));if (zoom) {} else {console.log("queryData0---: ", zoom);zoom = zoomOri + 1;console.log("queryData1---: ", zoom);}var url = "/geo?bounds=" + map.getBounds().toString().replaceAll('LngLat', '').replace('Bounds', '').replace('),', ';').replaceAll('(', '').replaceAll(')', '') + "&zoom=" + zoom;console.log('queryData: ', str, url);$.ajax({url: url, // ajax請求要請求的地址type: "get", // 請求的類型 get postsuccess: function (data) {// 請求成功之后要執(zhí)行的方法// data 接收請求成功之后的返回值map.getSource('earthquakes').setData(data);},error: function (error) {// 請求失敗之后要執(zhí)行的內(nèi)容}})}// 移動結(jié)束事件map.on('moveend', queryData);// 縮放完成事件map.on('zoomend', queryData);// 拖拽完成事件map.on('dragend', queryData);// 鼠標滾動map.on("wheel", queryData);viewMapOption();map.on('move', viewMapOption);map.on('mousemove', viewCoordinate);});function locationByXY() {var px = parseFloat($("#m_x").val());var py = parseFloat($("#m_y").val());map.setCenter([px, py]);}/*** 容器改變觸發(fā)*/function resizeMap() {//初始化寬度、高度$("#map").height($(window).height() - 150);//當文檔窗口發(fā)生改變時 觸發(fā)$(window).resize(function () {$("#map").height($(window).height() - 150);});}function viewCoordinate(evt) {if (evt != null) $("#i_coordinate").text("當前坐標:" + evt.lngLat.lng.toFixed(7) + "," + evt.lngLat.lat.toFixed(7));}/*** 顯示地圖狀態(tài)信息*/function viewMapOption() {var bounds = map.getBounds();console.log("級別=" + map.getZoom() + ",中心(" + bounds.getCenter().lng.toFixed(7) + "," + bounds.getCenter().lat.toFixed(7) + ")");console.log("邊界[" + bounds.getSouthWest().lng.toFixed(7) + "," + bounds.getSouthWest().lat.toFixed(7) + ";" + bounds.getNorthEast().lng.toFixed(7) + "," + bounds.getNorthEast().lat.toFixed(7) + "]");$("#i_click").text("級別=" + map.getZoom() + ",中心(" + bounds.getCenter().lng.toFixed(7) + "," + bounds.getCenter().lat.toFixed(7) + ")");$("#i_show").text("邊界[" + bounds.getSouthWest().lng.toFixed(7) + "," + bounds.getSouthWest().lat.toFixed(7) + ";" + bounds.getNorthEast().lng.toFixed(7) + "," + bounds.getNorthEast().lat.toFixed(7) + "]");}
</script></body>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet">
</html>
參考
- https://blog.csdn.net/qq_36120342/article/details/108752068
- https://gitee.com/liuhaomin/publicdemo/tree/master/dianjuhe 依賴mysql庫
- https://www.cnblogs.com/haibalai/p/9049625.html
總結(jié)
以上是生活随笔為你收集整理的Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Python,OpenCV进行形态学
- 下一篇: Mapbox gl tile瓦片渲染点以