概述
在前面的文章中,讲述了通过“抽稀+后台生成图片”的方式解决大量POI点展示的一种思路,后面看了tilestache的矢量切片方式,自己仔细思考了下,提出了本文大量POI点的展示解决方案。
tilestache
大概看了下tilestache,理解了下,大概解决思路是这样的:随着地图四至范围的变换,实时的去请求数据,并将数据在前段渲染,这样就大大提升了大量点的展示的效率问题。
效果
实现代码
1、后台实现
后台实现非常简单,通过servlet返回查询结果,根据四至作为条件进行查询,代码如下:
package com.lzugis.web; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSON; import net.sf.json.JSONArray; import org.springframework.jdbc.core.JdbcTemplate; import com.lzugis.db.SpringUtil; /** * Servlet implementation class PoiServlet */ @WebServlet(description = "poi servlet", urlPatterns = {"/getpois"}) public class PointsServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see javax.servlet.http.HttpServlet#HttpServlet() */ public PointsServlet() { super(); // TODO Auto-generated constructor stub } /** * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub this.doPost(request, response); } /** * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String bbox= request.getParameter("bbox"); int z = Integer.parseInt(request.getParameter("z").toString()); System.out.println(z+","+bbox); String[] extent = bbox.split(","); double xmin = Double.parseDouble(extent[0]), ymin = Double.parseDouble(extent[1]), xmax = Double.parseDouble(extent[2]), ymax = Double.parseDouble(extent[3]); JdbcTemplate jdbcTemplate = (JdbcTemplate) SpringUtil.getBean("jdbcTemplate"); String sqlQuery = "select * from county where x>=? and x<=? and y>=? and y<=?"; List<Map<String, Object>> list = jdbcTemplate.queryForList(sqlQuery, new Object[]{xmin,xmax,ymin,ymax}); JSON json = JSONArray.fromObject(list); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(json); out.flush(); out.close(); } }2、前台实现
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>openlayers map</title> <link rel="stylesheet" href="http://localhost:63342/lzugis/plugin/OpenLayers-2.13.1/theme/default/style.css" type="text/css"> <style> html, body, #map{ padding:0; margin:0; height:100%; width:100%; overflow: hidden; } </style> <script src="http://localhost:63342/lzugis/plugin/OpenLayers-2.13.1/OpenLayers.js"></script> <script src="http://localhost:63342/lzugis/plugin/jquery/jquery-1.8.3.js"></script> <script src="http://localhost:63342/lzugis/example/openlayers/ol2/extend/Grid.js"></script> <script> var map, sld; $(window).load(function() { var format = 'image/png'; var bounds = new OpenLayers.Bounds( 73.45100463562233, 18.16324718764174, 134.97679764650596, 53.531943152223576 ); var options = { controls: [], maxExtent: bounds, maxResolution: 0.2403351289487642, projection: "EPSG:4326", units: 'degrees' }; map = new OpenLayers.Map('map', options); var tiled = new OpenLayers.Layer.WMS( "Geoserver layers - Tiled", "http://localhost:8088/geoserver/lzugis/wms", { "LAYERS": 'province', "STYLES": '', format: format }, { buffer: 0, displayOutsideMaxExtent: true, isBaseLayer: true, yx : {'EPSG:4326' : true} } ); map.addLayers([tiled]); OpenLayers.INCHES_PER_UNIT["千米"] = OpenLayers.INCHES_PER_UNIT["km"]; OpenLayers.INCHES_PER_UNIT["米"] = OpenLayers.INCHES_PER_UNIT["m"]; OpenLayers.INCHES_PER_UNIT["英里"] = OpenLayers.INCHES_PER_UNIT["mi"]; OpenLayers.INCHES_PER_UNIT["英寸"] = OpenLayers.INCHES_PER_UNIT["ft"]; //比例尺 map.addControl(new OpenLayers.Control.ScaleLine({topOutUnits:"千米",topInUnits:"米",bottomOutUnits:"英里", bottomInUnits:"英寸" })); map.addControl(new OpenLayers.Control.Zoom()); map.addControl(new OpenLayers.Control.Navigation()); map.addControl(new OpenLayers.Control.OverviewMap()); map.zoomToExtent(bounds); var baseName = "http://localhost:8081/lzugis/getpois"; var protocol = new OpenLayers.Protocol.HTTP({ url: baseName }); var strategy = new OpenLayers.Strategy.Grid(); var vectors = new OpenLayers.Layer.Vector("Vector", { strategies: [strategy], protocol: protocol }); map.addLayer(vectors); var options = { hover: true }; var select = new OpenLayers.Control.SelectFeature(vectors, options); map.addControl(select); select.activate(); }); </script> </head> <body> <div id="map"> </div> </body> </html>在此处,调用了一个扩展的Strategy,该Strategy里实现了数据的实时调用与数据展示,扩展Grid.js代码如下:
OpenLayers.Strategy.Grid = OpenLayers.Class(OpenLayers.Strategy, { grid: null, buffer: 1, loadedBounds: null, zoom: null, geometryFeatureMap: {}, tiles: {}, initialize: function(options) { OpenLayers.Strategy.prototype.initialize.apply(this, [options]); }, destroy: function() { this.clearGrid(); this.grid = null; this.tileSize = null; OpenLayers.Strategy.prototype.destroy.apply(this, arguments); }, activate: function() { var activated = OpenLayers.Strategy.prototype.activate.call(this); if(activated) { this.layer.events.on({ "moveend": this.update, "refresh": this.update, scope: this }); if(this.layer.visibility == true || this.preload) { this.update(); } else { this.layer.events.on({ "visibilitychanged": this.load, scope: this }); } } return activated; }, deactivate: function() { var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this); if(deactivated) { this.layer.events.un({ "moveend": this.update, "refresh": this.update, "visibilitychanged": this.load, scope: this }); } return deactivated; }, loadData: function(bbox,zoom) { var scope = this; var url = scope.layer.protocol.url+"?bbox="+bbox+"&z="+zoom; $.ajax({ type : "POST", cache: false, url : url, async : false, success : function(data) { scope.readDone(data); } }); }, update: function() { var bounds = this.layer.map.getExtent(); if (bounds == null) return; var map = this.layer.map var curZoom = map.zoom; if (curZoom != this.zoom) { this.layer.destroyFeatures(); this.geometryFeatureMap = {}; this.tiles = {}; this.zoom = curZoom } this.loadData(bounds.toBBOX(),curZoom); }, readDone: function(data) { this.merge(data, this.options); }, merge: function(data, options) { var data = eval("("+data+")"); console.log("供查询到"+data.length+"条数据"); if(data.length > 0) { var features = []; for(var i=0, len=data.length; i<len; ++i) { var d = data[i]; var feature = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Point(d.x, d.y), d ); features.push(feature); } this.layer.addFeatures(features); } }, CLASS_NAME: "OpenLayers.Strategy.Grid" });
传播GIS知识 | 交流GIS经验 | 分享GIS价值 | 专注GIS发展
技术博客
http://blog.csdn.net/gisshixisheng
在线教程
http://edu.csdn.net/course/detail/799
Github
https://github.com/lzugis/
联系方式
q q:1004740957
e-mail:[email protected]
公众号:lzugis15
Q Q 群:452117357(webgis)
337469080(Android)