我寫的東西內容淺顯,希望能給初學者一些幫助。至於深入研究sharpmap和GIS技術的大牛,請不吝賜 教,給我們這些菜鳥多一些指導。
今天我們接著來聊sharpmap的基本使用技巧,根據attribute來填充地圖對象的顏色,讓用戶更清晰的 看到重點的業務對象對應在地圖上的表示,以及如何自定義label層的顯示內容,字體的大小等。所以,今 天的主題主要是自定義:自定義theme,自定義label以及label字體。
首先,我們要為地圖填充上不同的色彩,讓他們看起來五顏六色,容易分辨。比如河流和湖泊要填成 藍色,草地要填充上綠色,房子要填充上白色,道路要填充上青色等等。怎麼做呢?很簡單,先看下代碼 :
SharpMap.Rendering.Thematics.CustomTheme iTheme = new SharpMap.Rendering.Thematics.CustomTheme(GetMyStyle);
在初始化Map的時候,加上上面的一行代碼。它定義了一個自定義的Theme對象,這個對象的構造函數 需要傳入一個我們自己寫的方法(委托),這個方法裡面具體說明了這個 theme是如何定義的,方法代碼 如下:
private static SharpMap.Styles.VectorStyle GetMyStyle(SharpMap.Data.FeatureDataRow row) { SharpMap.Styles.VectorStyle style = new SharpMap.Styles.VectorStyle(); switch (row["Status"].ToString().ToLower()) { case "available": //If status is interred, fill it with yellow style.Fill = Brushes.Yellow; return style; default: style.Fill = Brushes.Green; return style; } }
這段簡單代碼大家都看得懂,這個委托定義需要傳入一個FeatureDataRow,它的作用就是在初始化地圖 的過程中,每處理一個對象,都要到這個方法中來考察一下feature的值是多少以決定具體要填充哪些顏 色。在這裡,當status為available時,就填充黃色,否則就填充綠色。定義的VectorStyle用來返回給地 圖。是不是很簡單呢?
地圖填充完了,我們要在上面顯示出到底他們是什麼。在第一篇中,我們已經可以把對象的一個屬性 顯示出來,但是當地圖擴大到一定比例時,僅僅顯示名字這一種信息已經不足以滿足用戶的需要了。比如 說一棟房子,在很遠處看它時,我們只需要看到他的顏色就行了。但是當我們離的很近的時候,難道看到 的是全白色嗎?顯然不是,我們還可以看到門牌號,窗戶上的貼紙以及其它詳細信息。地圖也一樣,當比 例尺改變以後,應該有更詳細的信息被列出來。老規矩,先貼代碼:
SharpMap.Layers.LabelLayer myLabel = new SharpMap.Layers.LabelLayer("labels"); myLabel .DataSource = myLayer.DataSource; myLabel.LabelStringDelegate= new SharpMap.Layers.LabelLayer.GetLabelMethod (GetLabelString);
在這裡,首先定義了一個label(就像在初始化地圖裡一樣,或者就在初始化地圖裡做),然後把你所 要顯示的圖層的數據源賦值給這個label的數據源,接著為label層的LabelStringDelegate指定一個方法 (這個方法傳入一個FeatureDataRow,返回一個字符串),最後去實現這個方法,代碼如下:
public static string GetLabelString(FeatureDataRow dr) { string field1= string.Empty; string field2= string.Empty; string field13= string.Empty; if (dr["HouseNumber"] != null) { field1= dr["HouseNumber"].ToString(); } if (dr["HostName"] != null) { field2= dr["HostName"].ToString(); } if (dr["Memo"] != null) { field3= dr["Memo"].ToString(); } StringBuilder sb = new StringBuilder(); sb.Append(field1); sb.Append(": "); sb.Append(field2); sb.Append("\r\n" + field3); return sb.ToString(); }
代碼簡單的要死,不再詳述,值得注意的是:如果要換行,請使用“\r\n”, 這裡不支持html拼的字 符串。哈,又解決一個問題。爽吧?
然後,新的問題又來了,字體一直都是那麼大,或者一直都是那麼小,這可怎麼辦呢?看起來也相當 不舒服啊。如果字體能隨著比例尺的變化而變化就好了。這個沒問題,我們馬上就搞定它。看代碼:
public void ChangeFontSize(double Zoom, SharpMap.Layers.ILayer iLayer) { SharpMap.Layers.LabelLayer labelLayer = (SharpMap.Layers.LabelLayer)iLayer; if (Zoom < 800 && Zoom > 400) { ((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 6); } else if (Zoom < 400 && Zoom > 140) { ((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 8); } else if (Zoom < 140.00 && Zoom > 20) { ((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 16); } else if (Zoom < 20.00) { ((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 48); } else { ((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 70); } }
這個方法傳入了一個Zoom值和一個ILayer,沒有返回值,直接修改ILayer就可以了。
相信大家都看得懂吧?值得注意的問題是:AjaxMap上面的map對象有個屬性叫做zoomAmount,這是個 javascript的屬性需要在前台指定,它說明了地圖放大或縮小的比例尺倍數。Demo中是在 RadioButtonList的ListItem中指定的。這個過程是這樣的:當點擊Zoom In這個button,自動執行了一段 javascript:
ajaxMapObj.disableClickEvent(); ajaxMapObj.zoomAmount = 3;
然後當我們點擊地圖,click事件已經被禁止,系統刷新地圖,此時在handler裡接受到了地圖的新的 參數(zoom等),然後重新繪制了地圖。所以,我們在handler裡取得zoom參數,並且使用 GetLayerByName(“”)方法來取得label層
ChangeFontSize(Zoom, map.GetLayerByName("mylabels"));
這樣,就實現了字體隨著比例尺變化兒變化。有同學可能問:那如何讓label的內容隨著比例尺變化而 變化呢?只需要把剛才那句話
myLabel.LabelStringDelegate= new SharpMap.Layers.LabelLayer.GetLabelMethod (GetLabelString);
放到相應的if。。else語句裡就行了。簡單吧?