功能:功能实现了现在网络流行的定位后在地图上画一个图标,点击图标后弹出消息框。
思路:根据查询条件获得一个点的地图坐标,然后转换为屏幕坐标,利用js脚本动态图片到相应位置。
效果图如下:
主要实现步骤:
1、SearchMapIdentity.cs,该类主要实现查询获取点的地图坐标,地图坐标转换为屏幕坐标的方法,点击小图标时的回发调用,代码如下:
using System; using System.Data; using System.Collections; using System.Collections.Specialized; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using ESRI.ArcGIS.ADF.Web; using ESRI.ArcGIS.ADF.Web.UI.WebControls; using ESRI.ArcGIS.ADF.Web.DataSources; using ESRI.ArcGIS.ADF.Web.Geometry; using ESRI.ArcGIS.ADF.Web.Display.Graphics; using System.Collections.Generic; namespace SearchMapIdentityTask{ public class SearchMapIdentity { #region 私有字段 private Page m_page; private Map m_map; private ArrayList mapPoints = null; private string content; private string m_callbackInvocation = ""; private string m_filePath = ""; private string queryText = ""; private DataTable queryResult = null; private string queryField = ""; private string readFields = ""; #endregion #region 相关属性 public Map Map { get { return m_map; } set { m_map = value; } } public Page Page { get { return m_page; } set { m_page = value; } } public string ClientCallbackInvocation { get { return m_callbackInvocation; } set { m_callbackInvocation = value; } } public string FilePath { get { return m_filePath; } set { m_filePath = value; } } public string QueryText { get { return queryText; } set { queryText = value; } } public ArrayList MapPoints { get { return mapPoints; } set { mapPoints = value; } } public string Content { get { return content; } set { content = value; } } public DataTable QueryResult { get { return queryResult; } set { queryResult = value; } } //需要用来作为Where条件的查询字段 public string QueryField { get { return queryField; } set { queryField = value; } } //需要显示在详细信息里的字段 public string ReadFields { get { return readFields; } set { readFields = value; } } #endregion #region 构造函数 public SearchMapIdentity() { } public SearchMapIdentity(Map map) { if (map != null) { m_map = map; } } public SearchMapIdentity(Map map, string filePath) { m_map = map; m_filePath = filePath; } #endregion #region 处理点击查询回调的函数 public void Identify(bool isFirstIdentify,string layername) { int x = 0; int y = 0; ArrayList xy = null; if (this.MapPoints == null || isFirstIdentify == true) { xy = GetXY(this.Map,layername); } else { xy = this.MapPoints as ArrayList; } foreach (object o in xy) { object[] arrayPoints = o as object[]; ESRI.ArcGIS.ADF.Web.Geometry.Point p = (ESRI.ArcGIS.ADF.Web.Geometry.Point)arrayPoints[0]; System.Drawing.Point screenPoint = MapToScreenPoint(p.X, p.Y); x = screenPoint.X; y = screenPoint.Y; string content = arrayPoints[1] as string; string oa = string.Format("ReDrawZommToPoint({0},{1},{2},{3},/'{4}/');", x, y, p.X, p.Y, content); CallbackResult cr1 = new CallbackResult(null, null, "javascript", oa); this.Map.CallbackResults.Add(cr1); } } #endregion #region 处理点击小图片时回调的函数 public void DrawInfoWin(double mapX, double mapY, string content) { System.Drawing.Point screen_point = MapToScreenPoint(mapX, mapY); int[] rate = { screen_point.X, screen_point.Y - 38 }; object[] oa = new object[1]; string sa = "showInfoWindow(" + rate[0].ToString() + "," + rate[1].ToString() + ",'" + content + "');"; oa[0] = sa; CallbackResult cr1 = new CallbackResult(null, null, "javascript", oa); this.Map.CallbackResults.Add(cr1); } #endregion #region 获得查询点的结果集 public ArrayList GetXY(Map Map1,string layername) { ArrayList XY = new ArrayList(); IEnumerable func_enum = Map1.GetFunctionalities(); System.Data.DataTable datatable = null; foreach (ESRI.ArcGIS.ADF.Web.DataSources.IGISFunctionality gisfunctionality in func_enum) { ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisresource = gisfunctionality.Resource; if (gisfunctionality.Resource.DataSource.DataSourceDefinition == "In Memory") { continue; } bool supported = gisresource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)); if (supported) { ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality qfunc; qfunc = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)gisresource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null); string[] lids; string[] lnames; qfunc.GetQueryableLayers(null, out lids, out lnames); int layer_index = -1; for (int i = 0; i < lnames.Length; i++) { if (lnames[i] == layername) { layer_index = i; break; } } if (layer_index == -1) { continue; } ESRI.ArcGIS.ADF.Web.SpatialFilter spatialfilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter(); spatialfilter.Geometry = Map1.GetFullExtent(); spatialfilter.ReturnADFGeometries = true; spatialfilter.MaxRecords = 1000; spatialfilter.WhereClause = this.QueryField + " like '%" + this.QueryText + "%'"; //txtSearch.Text; 查询条件 datatable = qfunc.Query(null, lids[layer_index], spatialfilter); this.QueryResult = datatable; if (datatable != null) { int intShape = -1; foreach (System.Data.DataColumn col in datatable.Columns) { if (col.DataType == typeof(Geometry)) { intShape = col.Ordinal; break; } } for (int i = 0; i < datatable.Rows.Count; i++) { ESRI.ArcGIS.ADF.Web.Geometry.Point point2 = (ESRI.ArcGIS.ADF.Web.Geometry.Point)datatable.Rows[i].ItemArray[intShape]; //让地图以某个点居中 this.Map.CenterAt(point2); Array readFieldPairs = this.ReadFields.Split(";".ToCharArray()); string[] readFieldValue; //循环构造Content属性 if (readFieldPairs.Length > 0) { for (int j = 0; j < readFieldPairs.Length-1; j++) { readFieldValue = readFieldPairs.GetValue(j).ToString().Split(":".ToCharArray()); this.Content += readFieldValue[0] + ":" + datatable.Rows[i][readFieldValue[1]].ToString()+"<br>"; } } object[] arraryPoint = new object[2]; arraryPoint[0] = point2; arraryPoint[1] = this.Content; //将Content属性清空 this.Content = ""; XY.Add(arraryPoint); } } } } this.MapPoints = XY; return XY; } #endregion #region 由地图坐标经过转换得到屏幕坐标的点 public System.Drawing.Point MapToScreenPoint(double mapX, double mapY) { ESRI.ArcGIS.ADF.Web.Geometry.Point adf_point = new ESRI.ArcGIS.ADF.Web.Geometry.Point(mapX, mapY); ESRI.ArcGIS.ADF.Web.Geometry.TransformationParams transformationParameters = this.Map.GetTransformationParams(ESRI.ArcGIS.ADF.Web.Geometry.TransformationDirection.ToScreen); System.Drawing.Point screen_point = adf_point.ToScreenPoint(transformationParameters); return screen_point; } #endregion } }
2、SearchMapIdentityTask.cs,这个就是包装Task的类,主要代码如下
using System; using System.Collections.Generic; using System.Text; using System.Web; using ESRI.ArcGIS.ADF.Web.UI.WebControls; using ESRI.ArcGIS.ADF.Web.DataSources; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Web.UI; using System.Collections; using System.Collections.Specialized; using System.Data; using System.ComponentModel; using System.Text.RegularExpressions; namespace SearchMapIdentityTask { public class SearchMapIdentityTask : FloatingPanelTask { private TextBox textBox = null; private HtmlInputButton button = null; private HtmlSelect selLayers = null; private HtmlInputButton clear = null; SearchMapIdentity searchMapIdentity = null; private string queryField = ""; private string readFileds = ""; #region 相关属性 [Description("用户where条件中要查询的字段")] public string QueryField { get { return queryField; } set { queryField = value; } } [Description("设置需要在详细信息中显示的字段,格式为(字段1中文名:字段1数据库表名;字段2中文名:字段2数据库表名)")] public string ReadFileds { get { return readFileds; } set { readFileds = value; } } #endregion #region 构造函数 public SearchMapIdentityTask() { this.Width = Unit.Pixel(200); } #endregion #region 构建子控件 protected override void CreateChildControls() { Controls.Clear(); base.CreateChildControls(); textBox = new TextBox(); textBox.ID = "textBox"; textBox.Width=200; button = new HtmlInputButton(); button.ID = "button"; button.Value = "查询"; clear = new HtmlInputButton(); clear.ID = "clear"; clear.Value = "清除结果"; selLayers = new HtmlSelect(); selLayers.ID = "sellayer"; Controls.Add(selLayers); Controls.Add(textBox); Controls.Add(button); Controls.Add(clear); string argument = string.Format("'args='+document.getElementById('{0}').value", selLayers.ClientID); argument += string.Format("+':'+strTrim(document.getElementById('{0}').value)", textBox.ClientID); string onClick = string.Format("executeTask({0},/"{1}/");", argument, base.CallbackFunctionString); //调用SearchMapIdentity.js里的clearIdentifyDiv函数,清楚上一次查询产生的div onClick += "clearIdentifyDiv();"; string onKeyDown = string.Format(" if(event.keyCode==13) {{{0} return false;}}", onClick); button.Attributes.Add("onclick", onClick); //点击clear按钮时,调用清除查询结果的js函数 clear.Attributes.Add("onclick", "clearIdentifyDiv()"); textBox.Attributes.Add("onkeydown", onKeyDown); //调用填充下拉框函数 FillLayerSelect(); } #endregion #region OnLoad—初始化一些初始变量 protected override void OnLoad(EventArgs e) { base.OnLoad(e); //进行相关属性检查 if (this.QueryField == "") { throw new Exception("QueryField属性未设置"); } Regex regex = new Regex("^(//S+://S+;)+$"); if (this.ReadFileds == "") { throw new Exception("ReadFileds属性未设置"); } else if (!regex.IsMatch(this.ReadFileds)) { throw new Exception("ReadFileds格式不正确,请查看描述后修改!"); } this.MapInstance.ScaleChanged += new MapScaleChangeEventHandler(Map_ScaleChanged); searchMapIdentity = new SearchMapIdentity(this.MapInstance); searchMapIdentity.QueryField = this.QueryField; searchMapIdentity.ReadFields = this.ReadFileds; //searchMapIdentity.SetupIdentify(); if (this.Page.Session["MapPoints"] != null) { searchMapIdentity.MapPoints = this.Page.Session["MapPoints"] as ArrayList; } } #endregion #region OnPreRender - 加载客户端脚本和设置属性 protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (this.Page != null) { //注册SearchMapIdentity脚本 ClientScriptManager scriptMgr = Page.ClientScript; Type controlType = this.GetType(); string fileName = controlType.Namespace + ".SearchMapIdentity.js"; scriptMgr.RegisterClientScriptResource(controlType, fileName); //注册回调的字符串 System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("<script language=/"javascript/" type=/"text/javascript/">var MapSearchIdentifyCallbackStr = /"" + base.CallbackFunctionString + "/";</script>/n"); if (!Page.ClientScript.IsClientScriptBlockRegistered("MapSearchIdentify")) Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "MapSearchIdentify", sb.ToString()); } } #endregion #region 回调处理函数 //得到传递进来的参数,赋给base.Input public override string GetCallbackResult() { NameValueCollection keyValCol1 = CallbackUtility.ParseStringIntoNameValueCollection(_callbackArg); if (keyValCol1["EventArg"] == "executeTask") { string sInArgs = keyValCol1["args"]; string delim = ":"; char[] delchar = delim.ToCharArray(); string[] args = sInArgs.Split(delchar); object[] inputs = new object[2]; inputs[0] = args[0]; inputs[1] = args[1]; base.Input = inputs; } else if (keyValCol1["EventArg"] == "startTaskActivityIndicator") { } else if (keyValCol1["EventArg"] == "hidden") { } //自己添加的分支,用户处理点击小图片是的回发处理 else if (keyValCol1["EventArg"] == "ShowInfoWin") { double MapX = Convert.ToDouble(keyValCol1["MapX"]); double MapY = Convert.ToDouble(keyValCol1["MapY"]); string content = keyValCol1["Content"]; searchMapIdentity.DrawInfoWin(MapX, MapY, content); return this.MapInstance.CallbackResults.ToString(); } return base.GetCallbackResult(); } #endregion #region 执行TASK public override void ExecuteTask() { if (Input == null) return; object[] inputs = Input as object[]; string selLayer = inputs[0] as string; string queryTxt = (string)inputs[1]; ViewState["selLayer"] = selLayer; ViewState["queryTxt"] = queryTxt; searchMapIdentity.QueryText = queryTxt; searchMapIdentity.Identify(true, selLayer); DataTable datatable = searchMapIdentity.QueryResult as DataTable; DataSet ds = new DataSet(); ds.Tables.Add(datatable); ds.DataSetName = "查询"+ queryTxt +"的结果为:"; Page.Session["MapPoints"] = searchMapIdentity.MapPoints; base.Results = ds; } #endregion #region 处理依赖资源 public override List<GISResourceItemDependency> GetGISResourceItemDependencies() { throw new Exception("The method or operation is not implemented."); } #endregion #region 渲染控件格式 protected override void RenderContents(HtmlTextWriter writer) { writer.RenderBeginTag(HtmlTextWriterTag.Table); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.RenderBeginTag(HtmlTextWriterTag.Td); this.selLayers.RenderControl(writer); writer.RenderEndTag(); writer.RenderEndTag(); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddStyleAttribute(HtmlTextWriterStyle.WhiteSpace, "nowrap"); writer.RenderBeginTag(HtmlTextWriterTag.Td); if (!string.IsNullOrEmpty(this.Input as string)) { this.textBox.Text = this.Input as string; } else { this.textBox.Text = ""; } this.textBox.RenderControl(writer); writer.RenderEndTag(); writer.RenderEndTag(); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.RenderBeginTag(HtmlTextWriterTag.Td); this.button.RenderControl(writer); writer.Write(" "); this.clear.RenderControl(writer); writer.RenderEndTag(); writer.RenderEndTag(); writer.RenderEndTag(); } #endregion #region 辅助函数 Map _map = null; TaskResults _taskResults = null; private Map MapInstance { get { if (_map == null) { for (int i = 0; i < base.TaskResultsContainers.Count; i++) { _taskResults = Utility.FindControl(TaskResultsContainers[i].Name, Page) as TaskResults; if (_taskResults != null && _taskResults.Map != null && _taskResults.Map.Length > 1) { _map = Utility.FindControl(_taskResults.Map, this.Page) as Map; } if (_map != null) break; } } return _map; } } private TaskResults getTaskResults() { if (_taskResults == null) _map = MapInstance; return _taskResults; } //填充selLayers下拉框 private void FillLayerSelect() { ListItem layerItem; IMapFunctionality mf = MapInstance.GetFunctionality(0); if (mf == null) { layerItem = new ListItem("<no layers found>", "null"); selLayers.Items.Add(layerItem); return; } IGISResource gisresource = mf.Resource; bool supported = gisresource.SupportsFunctionality(typeof(IQueryFunctionality)); selLayers.Items.Clear(); if (supported) { IQueryFunctionality qfunc = gisresource.CreateFunctionality(typeof(IQueryFunctionality), null) as IQueryFunctionality; string[] lids; string[] lnames; qfunc.GetQueryableLayers(null, out lids, out lnames, ESRI.ArcGIS.ADF.Web.FeatureType.Point); int i = 0; while (i < lnames.Length) { layerItem = new ListItem(lnames[i], lnames[i]); selLayers.Items.Add(layerItem); i++; } } } #endregion #region 地图比例尺变化以后要执行的函数 protected void Map_ScaleChanged(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ScaleEventArgs args) { if (Page.IsPostBack || Page.IsCallback) { if (ViewState["selLayer"] != null && ViewState["queryTxt"] != null) { searchMapIdentity.QueryText = "四川"; searchMapIdentity.Identify(false, ViewState["selLayer"] as string); } } } #endregion } }
3、SearchMapIdentity.js,主要是些动态创建和定位div的js脚本
//显示详细信息的服务器回调函数 function DrawInfowindow(mapX,mapY,content) { if (mapX==null||mapY==null) return; var argument="EventArg=ShowInfoWin&MapX=" + mapX + "&MapY=" + mapY + "&Content=" + content; var context = Maps["Map1"].controlName; eval(MapSearchIdentifyCallbackStr); } //删除已经标示的DIV function clearIdentifyDiv() { var o = map.overlayObject while (o.hasChildNodes()) { o.removeChild(o.lastChild); } } //将图片定位到指定点 function showZoomToPoint(x,y,mapX,mapY,content) { map = Maps["Map1"]; var pointdiv = document.createElement("div"); pointdiv.style.position="absolute"; pointdiv.style.zIndex=2; // point is bottom center... 2 pixels up for shadow var cWidth = Math.floor(pointdiv.clientWidth / 2); var cHeight = pointdiv.clientHeight; if (cWidth==0) cWidth = 20; if (cHeight==0) cHeight = 38; var idLeft = x - parseInt(map.divObject.style.left)-cWidth/2; var idTop = y - parseInt(map.divObject.style.top) - cHeight + 2; pointdiv.innerHTML='<img src=images/blank.gif alt="" border="0" hspace="0" vspace="0" οnclick=/'DrawInfowindow(' + mapX + ',' + mapY + ',"' + content + '");/' style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=/'images/icon_info.png/');cursor:hand;" />/n'; map.overlayObject.appendChild(pointdiv); pointdiv.style.left= idLeft; pointdiv.style.top=idTop; return false; } //重新将图片定位到指定点 function ReDrawZommToPoint(x,y,mapX,mapY,content) { window.setTimeout("showZoomToPoint(" + x + "," + y + "," + mapX + "," + mapY + ",/'" + content + "/')",1000); } //显示详细信息的函数 function showInfoWindow(x,y,content) { var div = document.getElementById("InfoWindow"); if (div==null) { addInfowindow(); } window.status=content; document.getElementById("infowindowTitle").innerHTML="<b><font color='black'>详细信息</font></b>" var infoContentHtml="<font color='black'>" + content + "</font><br>"; var oNearQuery=document.getElementById("tr_NearQuery"); infoContentHtml += "<span style=/"cursor:hand;/" οnclick=/"alert('call js functions u need');/"><u>点我吧</u></span> "; document.getElementById("infowindowContent").innerHTML= infoContentHtml ; var div = document.getElementById("InfoWindow"); var cWidth = Math.floor(div.clientWidth / 2); var cHeight = div.clientHeight; if (cWidth==0) cWidth = 235; if (cHeight==0) cHeight = 148; var idLeft = x - parseInt(map.divObject.style.left) ;//- cWidth; var idTop = y - parseInt(map.divObject.style.top) - cHeight + 2; window.setTimeout('moveLayer("InfoWindow", ' + idLeft + ', ' + idTop + '); showLayer("InfoWindow");', 0); return false; } //添加显示信息的div function addInfowindow() { var content=""; content = '<div id="InfoWindow" style="z-index:3;position:absolute; width:235px; height:148px;left: 0px; top: 0px; visibility: hidden; overflow:hidden; background-image: url(images/Info.gif); layer-background-image: url(images/Info.gif); border: 1px none #000000; cursor:default "><table border="0" cellpadding="0" cellspacing="0">'; content += '<tr> '; content += ' <td valign="top"><table width="235" border="0" cellspacing="0" cellpadding="0"> '; content += ' <tr> '; content += ' <td><table border="0" style="overflow: hidden;height: 20px; width:235px;" cellspacing="0" cellpadding="0"> '; content += ' <tr> '; content += ' <td id ="infowindowTitle" width="218" style="overflow: hidden; width:218px; height:20px; font:宋体; font-size:12px; color:black; padding-left:10px; " valign="middle"></td> '; content += ' <td width="17" valign="middle"><img style="cursor:hand;" οnclick=/'closeInfoWindow();/' οnmοuseοver="this.src=/'images/close2.png/'" οnmοuseοut="this.src=/'images/close1.png/'" src="images/close1.png" width="8" height="6" /></td> '; content += ' </tr> '; content += ' </table></td> '; content += ' </tr> '; content += ' <tr> '; content += ' <td > '; content += ' <table align="center" width="220" border="0" cellspacing="0" cellpadding="0"> '; content += ' <tr> '; content += ' <td background="images/h-line.png" style="height:1px; padding:10px"></td> '; content += ' </tr>'; content += ' </table> '; content += ' </td> '; content += ' </tr> '; content += ' <tr> '; content += ' <td style="height:125px; overflow:hidden; " valign="top"> '; content += ' <table width="230" style="width:230px; height:125px; overflow: hidden;" border="0" cellpadding="0" cellspacing="0"> '; content += ' <tr> '; content += ' <td valign="top"> '; content += ' <div id="infowindowContent" style="overflow: hidden;height:75px; width:230px; font-size:12px ;padding-left:10px;padding-top:10px" ></div> '; content += ' </td> '; content += ' </tr>'; content += ' </table></td> '; content += ' </tr> '; content += ' </table></td> '; content += ' </tr>'; content += '</table></div>'; map.overlayObject.insertAdjacentHTML("BeforeEnd", content); } //关闭显示详细信息的div function closeInfoWindow() { var div = document.getElementById("InfoWindow"); if (div!=null) { hideLayer("InfoWindow"); } } //辅助函数——清除字符串空格 function strTrim(s) { var reg=/(^/s*)|(/s*$)/g; var ss=s.replace(reg,""); return ss; }
使用注意事项:
1、要把附件中的图片Info.gif、close1.png、close2.png、h-line.png、icon_info.png拷贝到测试项目的根目录下的images文件夹下面。
2、要在mxd中添加1个以上点图层。