概述
在前面的文章中,讲述了通过“抽稀+后台生成图片”的方式解决大量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:niujp08@qq.com
公众号:lzugis15
Q Q 群:452117357(webgis)
337469080(Android)