(-:<转载时请注明本文由goldenhawking在 CSDN blog 撰写http://write.blog.csdn.net/postedit/7964712
只有栅格图层是没有意义的,我们需要矢量图层才能实现自己的功能。这里实现的功能是获取公司外派的外卖员的位置,并显示他们最后一次按动汇报器按钮的时刻,以便公司掌握这些员工的交通安全、买卖效率。员工ID 是唯一的工号,姓名、正在执行的送外卖对象的电话、地址。下面,我们来实现这个Web应用。
<0>、数据环境
数据使用PostgreSQL 视图发布,该视图主要字段:
1、id , 员工ID
2、s_tel, 员工电话
3、t_tel , 外卖对象电话
4、t_addr, 外卖对象位置
5、d_starttm 任务开始时刻
6、lat, 当前经度
7、lon ,当前纬度
8、GEO类型摩卡托坐标字段
CREATE TABLE express_status
(
id character varying(16) NOT NULL,
s_tel character varying(20),
t_tel character varying(20),
t_addr character varying(64),
d_starttm timestamp with time zone,
lat double precision NOT NULL DEFAULT 0,
lon double precision NOT NULL DEFAULT 0,
CONSTRAINT pk_id PRIMARY KEY (id )
)
WITH (
OIDS=FALSE
);
CREATE OR REPLACE VIEW view_express_status AS
SELECT express_status.id, express_status.s_tel, express_status.t_tel, express_status.t_addr, express_status.d_starttm, express_status.lat,
express_status.lon, st_transform(st_setsrid(st_makepoint(express_status.lon, express_status.lat), 4326), 900913) AS geobj
FROM express_status;
第八个字段,摩卡托投影的字段非常重要,使用 ST_Transform(ST_SetSRID(ST_MakePoint(lon,lat),4326),900913) 把经纬度的wgs84变为摩卡托的900913投影系,否则,在 OpenLayers 上就需要做很多的设置。
<1>、安装配置GeoSevrer
下载GeoServer到本地,这里是2.1.4版本。下载后,解压到喜欢的地方待用。这里设置在 ~/bin/geoserver-2.1.4下。
sudo nano /etc/environment
设置 JAVA_HOME 环境变量到安装的JAVA虚拟机(JVM)路径,/usr/lib/jvm/default-java
JAVA_HOME="/usr/lib/jvm/default-java"
设置GEOSERVER_HOME 到安装路径
GEOSERVER_HOME="/home/goldenhawking/bin/geoserver-2.1.4"
直接运行 $(GEOSERVER_HOME)/bin/startup.sh 即可启动。stop终止,很方便的。
测试,访问 127.0.0.1:8080/geoserver/web/出现起始页面即可。初始用户密码 admin : geoserver
<2> 创建新的数据服务
1、 在 Web页面上首先创建一个workspace 叫 expresstatus ,uri也是 expresstatus
2、创建 Stores,名字叫 storexpresstatus,工作空间是 expresstatus, 数据库连接写好后,会列出数据库里的表,选择我们的视图view_express_status,并publish
3、系统调到创建图层的界面,主要注意的是,全球摩卡托的 bbox 为 正负20037508.342789,换算过去纬度为正负85
测试地址http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=1,如果看到 下面的类似东西,就好啦:
<3> 为 OpenLays设置代理服务
这张视图存储在PostgreSQL服务器上,但是位于另外一台机器。我们的GeoServer也位于另外一台机器,所以,首先要做的是突破 Ajax 默认拒绝异地XMLRequest的安全限制。根据OpenLayers 2.10 Beginner's Guide - E. Hazzard 书中所说,到http://trac.osgeo.org/openlayers/browser/trunk/openlayers/examples/proxy.cgi下载proxy.cgi,拷到自己的/usr/lib/cgi-bin下,别忘了把geoserver 所在的ip 追加到proxy.cgi准许访问网站中。
# Designed to prevent Open Proxy type stuff.
17
18 allowedHosts = ['www.openlayers.org', 'openlayers.org',
19 'labs.metacarta.com', 'world.freemap.in',
20 'prototype.openmnnd.org', 'geo.openplans.org',
21 'sigma.openplans.org', 'demo.opengeo.org',
22 'www.openstreetmap.org', 'sample.azavea.com',
23 'v2.suite.opengeo.org', 'v-swe.uni-muenster.de:8080',
24 'vmap0.tiles.osgeo.org', '192.168.1.100:8080']
在 OpenLayers 的 init里,写入
OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url=';
这样,在下载时,Ajax即可访问与脚本所在位置不同的东东。
<4> 实现相关网页脚本
在前面章节的基础上,我们加入一个图层,并设置好单击的事件为在侧边的DIV上显示详细的信息。看看Init
function init() {
OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url='
map = new OpenLayers.Map("map", {
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.ScaleLine({ geodesic: true }),
new OpenLayers.Control.Permalink('permalink'),
//new OpenLayers.Control.KeyboardDefaults(),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.Attribution()],
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
maxResolution: 156543.0339,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
});
// This is the layer that uses the locally stored tiles
var newLayer = new OpenLayers.Layer.OSM("OSM Tiles", "/osm_tiles2/${z}/${x}/${y}.png", { numZoomLevels: 19, transitionEffect: "resize" });
map.addLayer(newLayer);
var vector_layer = new OpenLayers.Layer.Vector('Express Status', {
projection: new OpenLayers.Projection('EPSG:900913'),
protocol: new OpenLayers.Protocol.HTTP({
url: 'http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=50',
format: new OpenLayers.Format.GML({
extractAttributes:true
})
}),
strategies: [new OpenLayers.Strategy.Fixed()]
});
var vector_style = new OpenLayers.Style({
'fillOpacity': .4,
'strokeColor': '#aaee77',
'strokeWidth': 3,
'pointRadius': 8
});
var vector_style_select = new OpenLayers.Style({
'fillOpacity': .9,
'strokeColor': '#aaee77',
'strokeWidth': 3,
'pointRadius': 8
});
var vector_style_map = new OpenLayers.StyleMap({
'default': vector_style,
'select': vector_style_select
});
vector_layer.styleMap = vector_style_map;
map.addLayer(vector_layer);
map.addControl(new OpenLayers.Control.EditingToolbar(vector_layer));
//Add a select feature control
var select_feature_control = new OpenLayers.Control.SelectFeature(vector_layer);
map.addControl(select_feature_control);
select_feature_control.activate();
//Activate the control
map.addControl(new OpenLayers.Control.Graticule({ visible: false }));
var mousepos = new OpenLayers.Control.MousePosition({ div: document.getElementById('mousepos_div') });
map.addControl(mousepos);
map.addControl(new OpenLayers.Control.OverviewMap());
//map.addControl(new OpenLayers.Control.NavToolbar());
map.layers[1].events.register('featureselected', this, OnFeatureSelected);
map.layers[1].events.register('featureunselected', this, on_unselect_feature);
var navigationT = new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
enableKinetic: true
}
});
map.addControl(navigationT);
if (!map.getCenter()) {
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
map.setCenter(lonLat, zoom);
}
}
还有单击的事件,枚举所有的属性并显示
function OnFeatureSelected(event) {
var info_div = document.getElementById('nodelist');
info_div.innerHTML = '';
//Store the clusters
evt_selected = event.feature.attributes;
//Loop through the cluster features
for (var atn in evt_selected) {
//Update the div with the info of the photos
info_div.innerHTML += "<p>"
+ atn.toString()+":"+evt_selected[atn].toString()
+ "</p>";
}
}
function on_unselect_feature(event) {
//Store a reference to the element
var info_div = document.getElementById('nodelist');
//Clear out the div
info_div.innerHTML = 'Please Select a Point.';
}
网页:
完整网页代码
<html>
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8">
<title>OSM Local Tiles</title>
<link rel="stylesheet" href="/openlayers/theme/default/style.css"
type="text/css" />
<script src="/openlayers/OpenLayers.js"></script>
<script type="text/javascript">
// Start position for the map (hardcoded here for simplicity)
var lat = 31.27386;
var lon = 121.48132;
var zoom = 4;
var evt_selected;
var map; //complex object of type OpenLayers.Map
//Initialise the 'map' object
function init() {
OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi?url='
map = new OpenLayers.Map("map", {
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.ScaleLine({ geodesic: true }),
new OpenLayers.Control.Permalink('permalink'),
//new OpenLayers.Control.KeyboardDefaults(),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.Attribution()],
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
maxResolution: 156543.0339,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
});
// This is the layer that uses the locally stored tiles
var newLayer = new OpenLayers.Layer.OSM("OSM Tiles", "/osm_tiles2/${z}/${x}/${y}.png", { numZoomLevels: 19, transitionEffect: "resize" });
map.addLayer(newLayer);
var vector_layer = new OpenLayers.Layer.Vector('Express Status', {
projection: new OpenLayers.Projection('EPSG:900913'),
protocol: new OpenLayers.Protocol.HTTP({
url: 'http://192.168.1.100:8080/geoserver/expresstatus/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=expresstatus:view_express_status&maxFeatures=50',
format: new OpenLayers.Format.GML({
extractAttributes:true
})
}),
strategies: [new OpenLayers.Strategy.Fixed()]
});
var vector_style = new OpenLayers.Style({
'fillOpacity': .4,
'strokeColor': '#aaee77',
'strokeWidth': 3,
'pointRadius': 8
});
var vector_style_select = new OpenLayers.Style({
'fillOpacity': .9,
'strokeColor': '#aaee77',
'strokeWidth': 3,
'pointRadius': 8
});
var vector_style_map = new OpenLayers.StyleMap({
'default': vector_style,
'select': vector_style_select
});
vector_layer.styleMap = vector_style_map;
map.addLayer(vector_layer);
map.addControl(new OpenLayers.Control.EditingToolbar(vector_layer));
//Add a select feature control
var select_feature_control = new OpenLayers.Control.SelectFeature(vector_layer);
map.addControl(select_feature_control);
select_feature_control.activate();
//Activate the control
map.addControl(new OpenLayers.Control.Graticule({ visible: false }));
var mousepos = new OpenLayers.Control.MousePosition({ div: document.getElementById('mousepos_div') });
map.addControl(mousepos);
map.addControl(new OpenLayers.Control.OverviewMap());
//map.addControl(new OpenLayers.Control.NavToolbar());
map.layers[1].events.register('featureselected', this, OnFeatureSelected);
map.layers[1].events.register('featureunselected', this, on_unselect_feature);
var navigationT = new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
enableKinetic: true
}
});
map.addControl(navigationT);
if (!map.getCenter()) {
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
map.setCenter(lonLat, zoom);
}
}
function OnFeatureSelected(event) {
var info_div = document.getElementById('nodelist');
info_div.innerHTML = '';
//Store the clusters
evt_selected = event.feature.attributes;
//Loop through the cluster features
for (var atn in evt_selected) {
//Update the div with the info of the photos
info_div.innerHTML += "<p>"
+ atn.toString()+":"+evt_selected[atn].toString()
+ "</p>";
}
}
function on_unselect_feature(event) {
//Store a reference to the element
var info_div = document.getElementById('nodelist');
//Clear out the div
info_div.innerHTML = 'Please Select a Point.';
}
function Button_Mark_onclick() {
var lat = Text_lat.value;
var lon = Text_lon.value;
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var current_zoom = map.zoom;
map.setCenter(lonLat, current_zoom);
var point = new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var feature_point = new OpenLayers.Feature.Vector(point);
map.layers[1].addFeatures([feature_point]);
}
function Button_Goto_onclick() {
var lat = Text_lat.value;
var lon = Text_lon.value;
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var current_zoom = map.zoom;
map.setCenter(lonLat, current_zoom);
}
function Button_DMSMark_onclick() {
var lat = parseFloat(Text_DMS_Lat_Deg.value.toString()) + parseFloat(Text_DMS_Lat_Min.value.toString()) / 60.0 + parseFloat(Text_DMS_Lat_Sec.value.toString()) / 3600.0;
var lon = parseFloat(Text_DMS_Lon_deg.value.toString()) + parseFloat(Text_DMS_Lon_MIn.value.toString()) / 60.0 + parseFloat(Text_DMS_Lon_Sec.value.toString()) / 3600.0;
Text_lat.value = lat;
Text_lon.value = lon;
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var current_zoom = map.zoom;
map.setCenter(lonLat, current_zoom);
var point = new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var feature_point = new OpenLayers.Feature.Vector(point);
map.layers[1].addFeatures([feature_point]);
}
function Button_DMSGoto_onclick() {
var lat = parseFloat(Text_DMS_Lat_Deg.value.toString()) + parseFloat(Text_DMS_Lat_Min.value.toString()) / 60.0 + parseFloat(Text_DMS_Lat_Sec.value.toString()) / 3600.0;
var lon = parseFloat(Text_DMS_Lon_deg.value.toString()) + parseFloat(Text_DMS_Lon_MIn.value.toString()) / 60.0 + parseFloat(Text_DMS_Lon_Sec.value.toString()) / 3600.0;
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var current_zoom = map.zoom;
map.setCenter(lonLat, current_zoom);
}
</script>
<style type="text/css">
.style1
{
width: 100%;
height: 29px;
}
.style2
{
width: 100%;
height: 90%;
}
#Text_DMS_Lat
{
width: 32px;
}
#Text_DMS_Lat_Deg
{
width: 32px;
}
#Text_DMS_Lat_min
{
width: 32px;
}
#Text_DMS_Lat_sec
{
width: 32px;
}
#Text_DMS_Lon_deg
{
width: 32px;
}
#Text_DMS_Lon_MIn
{
width: 32px;
}
#Text_DMS_Lon_Sec
{
width: 32px;
}
</style>
</head>
<!-- body.onload is called once the page is loaded (call the 'init' function) -->
<body onload="init();">
<table class="style2">
<tr>
<td width="80%">
<div style="width: 100%; height: 100%" id="map">
</div>
</td>
<td width="20%">
<div style="width: 100%; height: 100%" id="nodelist">
</div>
</td>
</tr>
</table>
<!-- define a DIV into which the map will appear. Make it take up the whole window -->
<div style="width: 100%; height: 5%" id="mousepos_div">
</div>
<table class="style1">
<tr>
<td>
小数纬度:<input id="Text_lat" type="text" />经度:<input id="Text_lon"
type="text" /><input id="Button_Mark" type="button" value="标记"
onclick="return Button_Mark_onclick()" /><input
id="Button_Goto" type="button" value="前往"
onclick="return Button_Goto_onclick()" /></td>
<td>
</td>
<td>
纬度 :<input id="Text_DMS_Lat_Deg" type="text" />度<input id="Text_DMS_Lat_Min"
type="text" />分<input id="Text_DMS_Lat_Sec" type="text" />秒.经度:<input
id="Text_DMS_Lon_deg" type="text" />度<input id="Text_DMS_Lon_MIn"
type="text" />分<input id="Text_DMS_Lon_Sec" type="text" />秒</td>
<td>
<input id="Button_DMSMark" type="button" value="标记" onclick="return Button_DMSMark_onclick()" /><input id="Button_DMSGoto" type="button" value="前往" onclick="return Button_DMSGoto_onclick()" /></td>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</body>
</html>
下一篇,将开始介绍 基于native C++的 C/S 架构客户端的开发以及应用