最近公司搞一个离线地图项目。恰好我刚入职,这个任务就落到我头上了。咋搞?!???完全没头绪啊。
硬着头皮也要搞嘛!
经过痛苦的找资料,终于确定用openlayers实现。
1.先下载离线地图吧。通过MaptileDownloader1.95即可。
2.建立地图服务。将下载的地图放到openlayers下即可。
3.现在开始正式的代码部分,准备好了么?
<%@ page isELIgnored="true"%> <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%@ include file="/common/master.jsp"%> <html> <head> <link rel="stylesheet" href="<%=request.getContextPath()%>/css/style.css" type="text/css" /> <style> html ,body{ width: 100%; height: 100%; } #map { width: 100%; height: 100%; float: left; } .olControlPanel div { display: block; position: absolute; top: 0px; left: 190px; width: 60px; height: 23px; margin: 5px; } .olControlPanel .olControlMouseDefaultsItemActive { background-image: url("/openlayers/img/Pan.gif"); } .olControlPanel .olControlMouseDefaultsItemInactive { background-image: url("/openlayers/img/PanSelected.gif"); } .olControlPanel .olControlZoomBoxItemInactive { width: 60px; height: 23px; position: absolute; top: 0px; left: 250px; background-image: url("/openlayers/img/ZoomInSelected.gif"); } .olControlPanel .olControlZoomBoxItemActive { width: 60px; height: 23px; position: absolute; top: 0px; left: 250px; background-image: url("/openlayers/img/ZoomIn.gif"); } .olControlPanel .olControlSelectFeatureItemInactive { width: 60px; height: 23px; position: absolute; top: 0px; left: 310px; background-image: url("/openlayers/img/InfoSelected.gif"); } .olControlPanel .olControlSelectFeatureItemActive { width: 60px; height: 23px; position: absolute; top: 0px; left: 310px; background-image: url("/openlayers/img/Info.gif"); } #panel { width: 15%; height: auto; float: left; } .olControlEditingToolbar { margin-right: 90px; } .olControlEditingToolbar .olControlDrawFeaturePointItemActive { background-position: -77px -23px; /* background: #fff url(\'../openlayers/img/marker.png\') no-repeat left top;*/ } .olControlEditingToolbar .olControlDrawFeaturePointItemInactive { background-position: -77px -0px; } .olPopup { width: 300px ; height : auto; font-size: 10px; } .olPopupContent { height:inherit; width:inherit; } button { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif; position: absolute; font-size: 1.5em; text-transform: uppercase; padding: 7px 15px; width: 30px; border-radius: 10px; color: #FFF; text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.8); border-width: 5px; border-style: solid; border-color: transparent transparent rgba(0, 0, 0, 0.35); -moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none; -moz-border-left-colors: none; border-image: none; cursor: pointer; animation: 1s ease 0s alternate none infinite pulse; transition: #000 0.4s ease 0s, border 0.2s ease 0s, margin 0.2s ease 0s; z-index: 9999; filter: alpha(opacity = 70); /*IE滤镜,透明度50%*/ -moz-opacity: 0.7; /*Firefox私有,透明度50%*/ opacity: 0.7; /*其他,透明度50%*/ } #lineMenu { top: 50px; right: 10px; background: none repeat scroll 0% 0% rgba(25, 90, 198, 1); } #pointMenu { top: 150px; right: 10px; background: none repeat scroll 0% 0% #A0C3FD; } .menuContent { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif; position: absolute; font-size: 1.5em; text-transform: uppercase; padding: 7px 15px; width: 200px; height: 400px; overflow: auto; border-radius: 10px; color: #FFF; text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.2); border-width: 5px; border-color: transparent transparent rgba(0, 0, 0, 0.35); background: none repeat scroll 0% 0% rgba(254, 254, 254, 1); background-image:url("<%=request.getContextPath()%>/background/images/biienbg.png"); -moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none; -moz-border-left-colors: none; border-image: none; cursor: pointer; animation: 1s ease 0s alternate none infinite pulse; transition: #000 0.4s ease 0s, border 0.2s ease 0s, margin 0.2s ease 0s; z-index: 9999; filter: alpha(opacity = 70); /*IE滤镜,透明度50%*/ -moz-opacity: 0.7; /*Firefox私有,透明度50%*/ opacity: 0.7; /*其他,透明度50%*/ } #lines { top: 50px; right: 40px; display: none; color:#fff; } #lines img{ width:14px; } #points { top: 50px; right: 40px; display: none; } #fullScreen{ top: 4px; width: 26px; height: 28px; right: 10px; margin-right:3px; } .nav{ position: absolute; -moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none; -moz-border-left-colors: none; border-image: none; cursor: pointer; animation: 1s ease 0s alternate none infinite pulse; z-index: 9999; opacity: 0.7; top: 4px; width: 76px; height: 28px; right: 10px; margin-right:3px; } .nav img{ width: 26px; height: 28px; } form p{ margin-bottom: 10px; } form{ width:300px; height:auto; } form span{ font-size:15px; font-weight:bold; margin-left: 30%; } </style> <script src="<%=request.getContextPath()%>/js/openlayers/OpenLayers.js" type="text/javascript"></script> <link rel="stylesheet" href="<%=request.getContextPath()%>/css/zTreeStyle/zTreeStyle.css" type="text/css"> <script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.ztree.core-3.5.js"></script> <script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.ztree.excheck-3.5.js"></script> <script type="text/javascript"> var arrmarkers = new Array(); var sf; var editingToolbar; var pointFeatures= new Array(); var routeList = new Array(); var setting = { check: { enable: true, //chkStyle: "checkbox", chkboxType: { "Y": "s", "N": "s" } }, data: { simpleData: { enable: true } },callback: { //beforeCheck: beforeCheck, onCheck: onCheck, onClick: zTreeOnClick } }; var zNodes=[]; var panel; var draw; var navigater; var dragFeature; $(document).ready(function() { map = new OpenLayers.Map("map", { maxExtent : new OpenLayers.Bounds( -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892), numZoomLevels : 17, maxResolution : 156543.0339, units : \'m\', projection : "EPSG:900913", displayProjection : new OpenLayers.Projection( "EPSG:4326") }); layer = new OpenLayers.Layer.TMS( "基础层", "http://127.0.0.1:8080/googlemaps/openlayers/roadmap/", { \'type\' : \'png\', \'getURL\' : get_my_url }); map.addLayers([ layer ]); var lonLat = new OpenLayers.LonLat(113.26080, 23.12649); lonLat.transform(map.displayProjection, map .getProjectionObject()); map.setCenter(lonLat, 12); map.addControl(new OpenLayers.Control.PanZoomBar({position : new OpenLayers.Pixel(2, 15)})); map.addControl(new OpenLayers.Control.MousePosition()); map.addControl(new OpenLayers.Control.KeyboardDefaults()); //新增部分,将对vector_line这个图层定义一个样式,不使用默认样式 var styleMap = new OpenLayers.StyleMap( { "default" : new OpenLayers.Style( { fillOpacity : 1, strokeOpacity : 1, strokeColor : "#1f32e0", graphicWidth : 40, graphicHeight : 40, graphicYOffset : -40, //externalGraphic : ", externalGraphic : "${image}", labelXOffset : 0, labelYOffset : 50, label : "${label}", labelColor : "#efe9e2", pointRadius : 8, fillColor : "black", strokeColor : "#666666", strokeWidth : 4, graphicZIndex : 1 }), "select" : new OpenLayers.Style( { fillOpacity : 0.6, strokeOpacity : 0.8, strokeColor : "#000000", graphicWidth : 40, graphicHeight : 40, graphicYOffset : -40, externalGraphic : "${image}", pointRadius : 8, fillColor : "black", strokeColor : "#666666", strokeWidth : 4, graphicZIndex : 1 }) }); var pointStyle = new OpenLayers.StyleMap( { "default" : new OpenLayers.Style( { fillOpacity : 1, strokeOpacity : 1, strokeColor : "#1f32e0", graphicWidth : 40, graphicHeight : 40, graphicYOffset : -40, //externalGraphic : ", externalGraphic : "<%=request.getContextPath()%>/js/openlayers/img/marker.png", labelXOffset : 0, labelYOffset : 0, label : "${label}", labelColor : "#efe9e2", pointRadius : 8, fillColor : "black", strokeColor : "#666666", strokeWidth : 4, graphicZIndex : 1 }), "select" : new OpenLayers.Style( { fillOpacity : 0.6, strokeOpacity : 0.8, strokeColor : "#000000", graphicWidth : 40, graphicHeight : 40, graphicYOffset : -40, externalGraphic : "<%=request.getContextPath()%>/js/openlayers/img/marker.png", pointRadius : 8, fillColor : "black", strokeColor : "#666666", strokeWidth : 4, graphicZIndex : 1 }) }); geojson = new OpenLayers.Format.GeoJSON(); //创建GeoJSON类对象,用于解析JSON串 vector_line = new OpenLayers.Layer.Vector("线路", { styleMap : styleMap, rendererOptions : { zIndexing : true } }); vector_point = new OpenLayers.Layer.Vector("网点", { styleMap : pointStyle, rendererOptions : { zIndexing : true } }); map.addLayer(vector_line); //首先屏蔽掉默认的右键: map.div.oncontextmenu = function () { return false;}; // 创建select control sf = new OpenLayers.Control.SelectFeature(vector_line); // 创建select control sf4Point = new OpenLayers.Control.SelectFeature(vector_point); // 将select control添加到map上 map.addControl(sf); // 注册Select事件 sf.onSelect = onFeatureSelect4Edit; // 注册取消Select事件 sf.onUnselect = onFeatureUnselect; // 激活select control,否则select control不可用 sf.activate(); //取得路线 getLines(); getPoints(); }); function getPoints(){ //取得网点 vector_point.removeAllFeatures(); zNodes=[]; $.getJSON("sys/geOrgJson.action",function(data) { for ( var i = 0; i < data.point.length; i++) { tempFeature = geojson.read(data.point[i]); if(data.point[i].features[0].geometry.type=="Point"){ tempFeature.data=data.point[i]; pointFeatures[i]=tempFeature; vector_point.addFeatures(tempFeature);//read返回OpenLayers.Feature.Vector zNodes.push({id:data.point[i].features[0].properties.serialNo,serialNo:data.point[i].features[0].properties.serialNo, pId:data.point[i].features[0].properties.pSerialNo, name:data.point[i].features[0].properties.name,open:false,checked:true,number:data.point[i].features[0].properties.number,x:data.point[i].features[0].geometry.coordinates[0],y:data.point[i].features[0].geometry.coordinates[1]}); } } $.fn.zTree.init($("#treeDemo"), setting, zNodes); }); } function getLines(huidiao){ $("#lines").empty(); var lines = "<ul>"; var features= new Array(); vector_line.removeAllFeatures(); $.getJSON("sys/geRouteJson.action",function(data) { for ( var i = 0; i < data.line.length; i++) { tempFeature = geojson.read(data.line[i]); if (data.line[i].features[0].geometry.type == "LineString") { features[i]=tempFeature; vector_line.addFeatures(tempFeature);//read返回OpenLayers.Feature.Vector lines += "<li><input class=\'chenckBoxItm\' type=\'checkbox\' checked=\'checked\' name="+i+" id=\'"+data.line[i].features[0].geometry.id+"\'><span style=\'font-weight:bold;\'>"+ data.line[i].features[0].geometry.name+"</span>"; lines+="<ul id=\'a"+i+"\' class=\'updown\' style=\'display:none;margin-left:20px;\'>"; //lines+="<ul>"; for(var j =1;j<data.line[i].features.length;j++){ lines+="<li>"; lines+=data.line[i].features[j].geometry.name; if(j==1){ lines+="<img src=\'<%=request.getContextPath()%>/background/images/up_disabled.png\'/>"; }else{ lines+="<img src=\'<%=request.getContextPath()%>/background/images/up.png\' onclick=\'upOrder("+i+","+data.line[i].features[j-1].geometry.id+","+data.line[i].features[j].geometry.id+")\'/>"; } if(j==data.line[i].features.length-1){ lines+="<img src=\'<%=request.getContextPath()%>/background/images/down_disabled.png\'/></li>"; }else{ lines+="<img src=\'<%=request.getContextPath()%>/background/images/down.png\' onclick=\'upOrder("+i+","+data.line[i].features[j+1].geometry.id+","+data.line[i].features[j].geometry.id+")\'/></li>"; } } lines+="</ul></li>"; } } lines += "</ul>"; $(lines).appendTo("#lines"); $("#lines input[type=\'checkbox\']").bind("click",function() { var num=$(this).attr("name"); $(this).parent().parent().find("ul").hide("fast"); if ($(this).is(":checked")) { vector_line.addFeatures(features[num]); $(this).parent().find("ul").show("fast"); } else { $(this).parent().find("ul").hide("fast"); vector_line.removeFeatures(features[num]); } }); $("#lines li span").bind("click",function() { $(".updown").hide("fast"); if ($(this).parent().children("ul").is(":visible")) { $(this).parent().children("ul").hide("fast"); } else { $(this).parent().children("ul").show("fast"); } }); if (huidiao) { huidiao(); } }); } //调整顺序,+ function upOrder(element,orgId,id2){ $("#a"+element).show(); $.getJSON("sys/upOrder.action",{"id":orgId,"id2":id2},function(data) { getLines(function(){$("#a"+element).css("display","block");}); }); } function removeAllPopup() { var len = map.popups.length; for ( var i = len - 1; i >= 0; i--) { map.removePopup(map.popups[i]); } } function get_my_url(bounds) { var res = this.map.getResolution(); var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w)); var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h)); var z = this.map.getZoom(); var path = "" + z + "/" + x + "/" + y + "." + this.type; var url = this.url; if (url instanceof Array) { url = this.selectUrl(path, url); } return url + path; } function deleteOrg(event) { var feature=vector_point.getFeatureFromEvent(event); if(feature.data.id) { if(confirm("确定要删除吗?")) { $.getJSON("sys/deleteOrgById.action",{ids:feature.data.id},function(data) { if (data==null||data==""||data.info == "1") { alert("删除机构失败,机构可能被其他系统资源引用"); } else { removeAllPopup(); vector_point.removeFeatures(feature); alert("删除成功"); } }); } }else{ removeAllPopup(); vector_point.removeFeatures(feature); } getPoints(); } //关闭弹出窗口的函数 function onPopupClose(evt) { sf.unselect(selectedFeature); getPoints(); } //构造弹出窗口的函数 function onFeatureSelect4Edit(feature) { removeAllPopup(); if(draw!=null){ draw.deactivate(); } var html; if (feature.data.id) { var html=\'<iframe src="sys/org!edit.action?ids=\'+feature.data.id+\'&xcode=\'+feature.geometry.x+\'&ycode=\'+feature.geometry.y+\'" width="400px" height="200px"></iframe> \'; } else { var html=\'<iframe src="sys/org!edit.action?xcode=\'+feature.geometry.x+\'&ycode=\'+feature.geometry.y+\'" width="400px" height="200px"></iframe> \'; } selectedFeature = feature; popup = new OpenLayers.Popup.Anchored("chicken", feature.geometry.getBounds().getCenterLonLat(),new OpenLayers.Size(250, 75), html,null, true, onPopupClose); feature.popup = popup; map.addPopup(popup); $(".olPopup").css("width", "inherit"); $(".olPopup").css("height", "inherit"); $(".olPopupContent").css("width", "inherit"); $(".olPopupContent").css("height", "inherit"); } //销毁弹出窗口的函数 function onFeatureUnselect(feature) { map.removePopup(feature.popup); feature.popup.destroy(); feature.popup = null; } function drag(feature){ $.getJSON("sys/updateLocation.action",{"id":feature.data.id,"xcode":feature.geometry.x,"ycode":feature.geometry.y},function(data) { }); } function showLines() { removeAllPopup(); $(\'#points\').hide("fast"); $("#lineMenu").css("background", "rgba(25, 90, 198, 1)"); $("#pointMenu").css("background", "#A0C3FD"); if ($(\'#lines\').is(\':visible\')) { $(\'#lines\').hide("fast"); } else { $(\'#lines\').show("fast"); } getLines(); if (navigater != null) { navigater.activate(); } draw.deactivate(); panel.addControls([ navigater ]); map.removeControl(draw); map.removeControl(panel); if (vector_point != null) { map.removeLayer(vector_point,false); } if (vector_line != null) { map.addLayer(vector_line); } } function showPoints() { removeAllPopup(); $("#pointMenu").css("background", "rgba(25, 90, 198, 1)"); $("#lineMenu").css("background", "#A0C3FD"); if ($(\'#points\').is(\':visible\')) { $(\'#points\').hide("fast"); } else { $(\'#points\').show("fast"); } $(\'#lines\').hide("fast"); if (vector_line != null) { map.removeLayer(vector_line,false); } if (vector_point != null) { map.addLayer(vector_point); } panel = new OpenLayers.Control.Panel({ displayClass : "olControlEditingToolbar" }); draw = new OpenLayers.Control.DrawFeature(vector_point, OpenLayers.Handler.Point, { displayClass : "olControlDrawFeaturePoint", title : "添加网点" }); navigater = new OpenLayers.Control.Navigation({ title : "Navigate" }); dragFeature=new OpenLayers.Control.DragFeature(vector_point); dragFeature.onComplete=drag; panel.addControls([ navigater, draw ]); //navigater.activate(); draw.featureAdded = onFeatureSelect4Edit; map.addControl(panel); map.addControl(dragFeature); //激活控件 dragFeature.activate(); // 将select control添加到map上 map.addControl(sf4Point); // 激活select control,否则select control不可用 sf4Point.activate(); // 注册Select事件 sf4Point.onSelect = onFeatureSelect4Edit; // 注册取消Select事件 sf4Point.onUnselect = onFeatureUnselect; var mouseRight = new OpenLayers.Control(); OpenLayers.Util.extend(mouseRight, { contextmenu: function(e) {deleteOrg(e); }, setMap: function() { OpenLayers.Control.prototype.setMap.apply(this, arguments); this.map.events.register( \'contextmenu\', this, this.contextmenu); }}); mouseRight.activate(); map.addControl(mouseRight); var treeObj = $.fn.zTree.getZTreeObj("treeDemo"); if(treeObj!=null){ treeObj.refresh(); } } function onCheck(e, treeId, treeNode) { if (treeNode.checked) { var x = treeNode.x; var y = treeNode.y; var lonLat = new OpenLayers.LonLat(x, y); map.setCenter(lonLat); for ( var ii = 0; ii < zNodes.length; ii++) { var serialNo = zNodes[ii].id.substring(0, treeNode.serialNo.length); if (serialNo == treeNode.serialNo) { vector_point .addFeatures(pointFeatures[zNodes[ii].number - 1]); } } } else { vector_point.removeFeatures(pointFeatures[treeNode.number - 1]); for ( var ii = 0; ii < zNodes.length; ii++) { var serialNo = zNodes[ii].id.substring(0,treeNode.serialNo.length); if (serialNo == treeNode.serialNo) { vector_point.removeFeatures(pointFeatures[zNodes[ii].number - 1]); } } } } function full() { window.parent.full(); } //网点点击事件 function zTreeOnClick(e,treeId, treeNode) { var x = treeNode.x; var y = treeNode.y; var lonLat = new OpenLayers.LonLat(x, y); map.setCenter(lonLat); } </script> </head> <body> <div id="map"></div> <div class="nav"> <img id="fullScreen" src="<%=request.getContextPath()%>/background/images/fullScreen.png" onclick="full();"/> <a href="<%=request.getContextPath()%>/openMap.action"><img src="<%=request.getContextPath()%>/background/images/task.png"/></a> </div> <button id="lineMenu" onclick="showLines()">线路</button> <button id="pointMenu" onclick="showPoints()">网点</button> <div id="lines" class="menuContent"></div> <div id="points" class="menuContent"> <div class="zTreeDemoBackground left"> <ul id="treeDemo" class="ztree"></ul> </div> </div> </body> </html>
解释下上述代码:
地图中有三个图层,一个基础图层,不可修改,一个点图层,一个线图层。
其中,点图层中,显示的是机构,图层中有一个菜单,是通过Ztree建立的树形结构。通过勾选显示,并且单击可定位。线图层中,显示的是网点的连线,同样也有一个菜单,通过菜单,可以调整线路中,点连线的顺序。
网点选择时候,会弹出菜单进行编辑。可以进行拖动,改变其位置。
另外,右键菜单是删除点操作。右键操作需要修改openlayers的库文件,如何修改,请参照:http://blog.csdn.net/sen2046/article/details/2735601即可。
话不多说,很伤心,之前写这文章,很详细的,可是快完成的时候,firefox崩溃了。我也跟着崩溃了。只好重写,没那么详细了!