What will you do when you want to tell your friends where your favorite restaurant is? Tell them the address? Yes, good, but how about to point it out on map? In this topic, we will discuss how to implement sharing position functionality in MapGuide based Web GIS application, which is running as public service, just like Google Maps or Bing Maps.
當你要告訴您的朋友您最喜歡的餐館在哪裏的時候,你會怎麼做?告訴他們地址?是的,很好,但怎麼樣在地圖上指出來呢?在這一主題中,我們將討論如何實現基於 MapGuide Web GIS 應用的地圖共享功能,這是作爲公共服務來運行,就像谷歌。
Firstly we find the restaurant on the map, and generate the link of current view, the link can be send to friends by email or IM tools, and of cause we can also embed the map into any page. Secondly, when we receive such a link and open it in browser, it should zoom to the specified view port automatically.
首先,我們在地圖上找到餐廳位置,併產生當前視圖的鏈接,該鏈接可以通過電子郵件或即時通訊工具發送給朋友,當然我們也可以將此地圖嵌入到任何網頁上。然後,我們將收到這樣一個鏈接並在瀏覽器打開,它將自動放大到指定的視圖位置。
I prefer to use Fusion viewer in this topic. Fusion is a web mapping application development framework. It allows web designers and developers to build rich mapping applications quickly and easily. Using "widgets" that provide the interface functionality within Fusion's modular architecture; developers are able to add, remove, or modify functionality using standard-compliant HTML and CSS. We need to create webpage and edit the flexible web layout in MapGuide Studio to add it to Task Pane:
在這個主題中我更喜歡使用 Fusion Viewer 。 Fusion 是一個 Web 地圖應用開發框架。它允許 Web 設計和開發人員容易並快速地構建豐富的地圖應用。在 Fusion 的模塊化體系結構中使用“小窗件”以提供界面接口功能;使用符合標準的 HTML 和 CSS 允許開發者具有添加,刪除或修改的功能。我們需要創建網頁並在 MapGuide Studio 中編輯靈活網絡佈局同時將它添加到任務窗格:
MapGuide Fusion Viewer provides many widgets, which implemented using JavaScript. We can get the center of map and current scale by Fusion Viewer API, and then pass these parameters to home page of MapGuide web application.
MapGuide 的 Fusion Viewer 提供了許多“小窗件”, 這些“小窗件”使用 JavaScript 實現。我們可以利用 Fusion Viewer API 獲取當前地圖的中心座標及比例,然後通過這些參數傳遞到 MapGuide Web 應用程序主頁面。
< html xmlns ="http://www.w3.org/1999/xhtml">
< head runat ="server">
< title >Send to friends</ title >
< script language ="javascript" type ="text/javascript">
// <!CDATA[
var mapWidgetId = 'Map' ;
var serverUrl = "http:// ServerName /SharePosition/default.aspx" ;
function Generate_onclick() {
var Fusion = window.top.Fusion;
var mapWidget = Fusion.getWidgetById(mapWidgetId);
//Get the parameters of current view
var centerX = mapWidget.getCurrentCenter().x;
var centerY = mapWidget.getCurrentCenter().y;
var scale = mapWidget.getScale()
//Generate the URL
var gotoUrl = serverUrl + "?x=" + centerX + "&y=" + centerY + "&scale=" + scale;
document.getElementById( "url" ).innerHTML = gotoUrl;
}
// ]]>
</ script >
</ head >
< body >
< form id ="form1" runat ="server">
< div >
< input id ="Generate" type ="button" value ="Generate Current View URL" onclick ="return Generate_onclick()" />< br />
< div id ="url"></ div >
</ div >
</ form >
</ body >
</ html >
Now, let's make the home page. To avoid MapGuide authentication login dialogue, we create a MapGuide connection and generate the session string, then pass it to the viewer path.
現在,讓我們產生主頁面。爲了避免 MapGuide 的身份驗證登錄對話框,我們創建一個 MapGuide 的連接並生成會話字符串,然後將它傳遞給瀏覽者的路徑。
In the web application home page, we will try to get view port parameters from the URL. If such parameters are attached in URL, it maybe a URL received from friends, the map should jump the specified view port; otherwise map should load the initial view port.
在 Web 應用程序的主頁,我們將嘗試從網址獲取視圖位置參數。如果這些參數在所附的網址裏,它可能是來自朋友的網址,地圖將跳到指定的視圖位置,否則地圖應程序加載初始視圖位置。
protected void Page_Load( object sender, EventArgs e)
{
// default flexible weblayout
string webLayout = @"Library://Samples/Sheboygan/FlexibleLayouts/Slate.ApplicationDefinition" ;
string viewerPathSchema = @"http:// ServerName /mapguide2010/fusion/templates/mapguide/slate/index.html?ApplicationDefinition={1}&SESSION={0}" ;
string defaultUser = "Administrator" ;
string defaultPassword = "admin" ;
Utility utility = new Utility ();
utility.InitializeWebTier(Request);
MgUserInformation userInfo = new MgUserInformation (defaultUser, defaultPassword);
MgSiteConnection siteConnection = new MgSiteConnection ();
siteConnection.Open(userInfo);
MgSite site = siteConnection.GetSite();
string sessionId = site.CreateSession();
//store in session for further use
Session[ "sessionId" ] = sessionId;
if (Request[ "X" ] != null && Request[ "Y" ] != null && Request[ "scale" ] != null )
{
string centerX = Request[ "X" ].ToString();
string centerY = Request[ "Y" ].ToString();
string scale = Request[ "scale" ].ToString();
//Generate the new weblayout resource identifier
webLayout = utility.ChangeInitialViewInWebLayout(webLayout, sessionId, centerX, centerY, scale);
}
string viewerPath = string .Format(viewerPathSchema, sessionId, Server.UrlEncode(webLayout));
Response.Redirect(viewerPath);
}
Now, we will discuss how to make the map jump to specified view port when it is loaded. In Autodesk MapGuide Studio, we can edit the flexible web layout using web layout editor. The default setting for "Initial view of map" is "use map's initial view"; it also can be specified value as below:
現在,我們將討論以上頁面被加載時如何使查看地圖跳轉到指定的視圖位置。在 Autodesk MapGuide Studio 中,我們可以使用網絡佈局編輯器編輯靈活網頁佈局。默認的 “地圖初始視圖” 設置爲“使用地圖的初始視圖”;你還可以指定爲以下值:
The application definition xml would be changed as below when it is saved, you can get the xml by Maestro conveniently, please pay attention to the <Initial View> section marked as bold.
當以上設置保存時該應用程序的 XML 定義改變如下,你可以通過 Maestro 方便地獲取該 XML ,請注意標記爲粗體部分的 <Initial View> 。
< MapGroup id = " Sheboygan " >
< InitialView >
< CenterX > -87.730254250934 </ CenterX >
< CenterY > 43.744459064634 </ CenterY >
< Scale > 22324609.319122165 </ Scale >
</ InitialView >
< Map >
…
</ Map >
< Extension />
</ MapGroup >
OK, as we have known the mechanism, let's implement it in code. We will add the <Initial View> section for the web layout. But there is another thing we need to care about, we are not going to change the web layout stored in library repository, because it will affect all the users. In order not to confuse other users, we need to create a temporary web layout based the current session. Code goes as below:
好了,正如我們所知道的原理,讓我們用代碼來實現。我們將爲網絡佈局添加 <Initial View> 節點。但還有另一件事情我們必須關注,我們並沒有改變在庫倉儲中網頁的佈局,因爲它會影響所有用戶。爲了不混淆其他的用戶,我們需要創建一個臨時的基於當前會話的網絡佈局。代碼如下:
public string ChangeInitialViewInWebLayout( string webLayoutTemplate, string sessionId, string centerX, string centerY, string scale)
{
if (siteConnection == null )
{
MgUserInformation userInfo = new MgUserInformation (sessionId);
siteConnection = new MgSiteConnection ();
siteConnection.Open(userInfo);
}
MgResourceIdentifier layoutResId = new MgResourceIdentifier (webLayoutTemplate);
MgResourceService resSvc = siteConnection.CreateService( MgServiceType .ResourceService) as MgResourceService ;
MgByteReader reader = resSvc.GetResourceContent(layoutResId);
System.IO. MemoryStream ms = new System.IO. MemoryStream ();
byte [] buf = new byte [8 * 1024];
int read = 1;
while (read != 0)
{
read = reader.Read(buf, buf.Length);
ms.Write(buf, 0, read);
}
string layoutXml = GetStringFromMemoryStream(ms);
XmlDocument doc = new XmlDocument ();
doc.LoadXml(layoutXml);
// if using custom view in web layout defintion, change the custom view port
if (doc.GetElementsByTagName( "InitialView" ).Count > 0)
{
XmlNode nodeCenterX = doc.GetElementsByTagName( "CenterX" ).Item(0);
nodeCenterX.InnerText = centerX;
XmlNode nodeCenterY = doc.GetElementsByTagName( "CenterY" ).Item(0);
nodeCenterY.InnerText = centerY;
XmlNode scaleNode = doc.GetElementsByTagName( "Scale" ).Item(0);
scaleNode.InnerText = scale;
}
else // using the map's initial view, we need to add a custom view port ourselves.
{
//Add <InitialView> tag for the web layout(application definition)
XmlNode initialViewNode = doc.CreateNode( XmlNodeType .Element, "InitialView" , null );
XmlNode centerXNode = doc.CreateElement( "CenterX" );
centerXNode.InnerText = centerX;
XmlNode centerYNode = doc.CreateElement( "CenterY" );
centerYNode.InnerText = centerY;
XmlNode scaleNode = doc.CreateElement( "Scale" );
scaleNode.InnerText = scale;
initialViewNode.AppendChild(centerXNode);
initialViewNode.AppendChild(centerYNode);
initialViewNode.AppendChild(scaleNode);
//insert before the <Map> tag
doc.GetElementsByTagName( "MapGroup" )[0].InsertBefore(initialViewNode, doc.GetElementsByTagName( "Map" )[0]);
}
MgByteSource byteSource = ByteSourceFromXMLDoc(doc);
string sessionLayoutName = layoutResId.GetName();
string sessionLayout = "Session:" + sessionId + @"//" + sessionLayoutName + ".ApplicationDefinition" ;
MgResourceIdentifier sessionLayoutResId = new MgResourceIdentifier (sessionLayout);
resSvc.SetResource(sessionLayoutResId, byteSource.GetReader(), null );
return sessionLayout;
}
Here is the test result, zoom you map to something you are interested in and want to share, press the "Generate Current View URL", an URL like http://serverName/SharePosition/default.aspx?x=-87.699801035788&y=43.751721697876&scale=3200.000005286838 will be generated. You can copy the follow URL
and send it to friends by mail or IM tools. When they open the URL, the map will jump to the same view port as yours. Enjoy!
下面是測試結果,縮放你的地圖到你感興趣並希望共享的地方,按“ Generate Current View URL ”按鈕,一個像 http://serverName/SharePosition/default.aspx?x=-87.699801035788&y=43.751721697876&scale=3200.000005286838 將會生成。你可以複製該 URL 網址並通過 Email 或即時通訊工具發送給朋友。當他們打開此網址,地圖就會跳到跟你一樣的視圖位置。試一下吧!
You are also welcome to discuss MapGuide related issue at http://www.newmgdn.com .
同時也歡迎您通過 http://www.newmgdn.com 討論 MapGuide 中的有關問題。