跳轉到內容

XRX/地圖導航

來自華夏公益教科書,開放的書籍,為一個開放的世界
< XRX

您希望在您的 XRX 應用程式中新增地圖導航功能。

雖然地圖控制元件沒有在原始 XForms 規範中定義,但可以透過使用一些 JavaScript 來新增它們。

我們將使用三個框架。

  1. XSLTForms - 用於啟用模型、控制元件和繫結
  2. JQuery - JQuery UI,JQuery 佈局 - 用於使用者介面。這包括控制元件來進行北、南、東、西方向的平移
  3. OpenLayers - 用於地圖導航、平移和縮放功能

XForms 模型將包含以下內容

  1. 一個包含搜尋查詢的預設例項,其中包含最小和最大經度和緯度(預設值)。
  2. 一個用於儲存查詢響應的位置(響應)。
  3. 一個定位例項(定位)
  4. 一些繫結語句
  5. 一個提交,用於從 openmap 資料庫獲取新的地圖資料

示例使用者介面

[編輯 | 編輯原始碼]

此示例具有一個簡單的地圖使用者介面控制元件,允許向北/南/東/西平移以及縮放和縮小。

此使用者介面使用一個與 XForms 輸入使用者介面控制元件關聯的 JQuery 物件。

示例模型原始碼

[編輯 | 編輯原始碼]

以下內容儲存在 XForms 模型中

請注意,以下名稱空間在此示例中使用

xmlns:geo="http://schematronic.ru/geo"
xmlns:param="http://schematronic.ru/param"
xmlns:ev="http://www.w3.org/2001/xml-events"
<xf:model>
   <!-- this holds the parameters for the outbound search query. -->
   <xf:instance id="default" xmlns="http://schematronic.ru/geo">
       <geo:search>
           <param:query/>
           <!-- variables for the min and max longitude and latitude -->
           <param:min-lon/>
           <param:min-lat/>
           <param:max-lon/>
           <param:max-lat/>
        </geo:search>
    </xf:instance>

    <!-- this holds the search results -->
    <xf:instance xmlns="" id="response">
       <response/>
    </xf:instance>

    <xf:instance id="locate">
       <eval>
           javascript:g.locate(<lon></lon>, <lat></lat>, "<icon></icon>")
       </eval>
    </xf:instance>

    <!-- These binds associate an id with a variable in the search form and a calculation -->
    <xf:bind id="query" nodeset="instance('default')/param:query"/>
    <xf:bind id="min-lon" nodeset="instance('default')/param:min-lon" calculate="min-lon()"/>
    <xf:bind id="min-lat" nodeset="instance('default')/param:min-lat" calculate="min-lat()"/>
    <xf:bind id="max-lon" nodeset="instance('default')/param:max-lon" calculate="max-lon()"/>
    <xf:bind id="max-lat" nodeset="instance('default')/param:max-lat" calculate="max-lat()"/>
    <!-- These binds associate an ID with 
    <xf:bind id="lon" nodeset="instance('locate')/lon"/>
    <xf:bind id="lat" nodeset="instance('locate')/lat"/>
    <xf:bind id="icon" nodeset="instance('locate')/icon"/>

    <!-- When the user selects any of the navigation controls, the following does a POST to the server. -->
    <!-- Note that the response to the search is places in the "response instance -->
     <xf:submission id="do-search" method="post" ref="instance('default')" replace="instance" instance="response" resource="/gate">
         <xf:load 
            ev:event="xforms-submit-done" 
            resource="javascript:showResult()"/>
     </xf:submission>
</xf:model>

JavaScript 匯入

[編輯 | 編輯原始碼]

Javascript 庫將來自 openstreemap.org 網站。我們還將使用一些 JQuery 使用者介面控制元件。

以下是您需要新增的靜態 JavaScript 檔案。

匯入靜態 JavaScript 庫

[編輯 | 編輯原始碼]
   <script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js"></script>
   <script type="text/javascript" src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
   <script type="text/javascript" src="/share/geo.js"></script>
   <script type="text/javascript" src="/share/jquery.js"></script>
   <script type="text/javascript" src="/share/jquery-ui.js"></script>
   <script type="text/javascript" src="/share/jquery-layout.js"></script>

內聯 JavaScript 資料

[編輯 | 編輯原始碼]

除了以上內容外,還必須使用以下 JavaScript 資料。

<script type="text/javascript">
    var g;
    function map(){
       var lat  = 51.30505;
       var lon  = 37.85331;
       var zoom = 12;
       g = geo("map", lon, lat, zoom);            
    }
    var isDebug = false;                   
    var layout;
  
    function showResult (){
                    layout.open("west");
    }      
    jQuery(function (){      
        jQuery("#search input").addClass("ui-state-default ui-corner-left");
        jQuery("#search button").addClass("ui-button ui-state-default ui-corner-right");
        layout = jQuery("body").layout({
              north : {
                            resizable          : false,
                            slidable           : false,
                            closable           : false,
                            spacing_open       : 0,
                            spacing_closed     : 0,
                            size               : 40
                        },
              south : {
                            size               : 100,
                            resizable          : true,
                            slidable           : true,
                            closable           : true,
                            initHidden         : !isDebug
                        },
              west : {
                            size               : 300,
                            minSize            : 200,
                            maxSize            : 400,
                            resizable          : true,
                            slidable           : true,
                            closable           : true,
                            initHidden         : true
                        }
                        
                    }); 
             map();             
     if (isDebug) jQuery("#console").show();    
})

</script>

表單主體

[編輯 | 編輯原始碼]
<body>
   <div id="header" class="ui-layout-north ui-widget-header">
      <span id="logo">
         <a href="/">
            <img src="/site/stkurier/images/logo/logo.png" alt="logo" />
         </a>
      </span>
      <span id="search">
          <xf:input xmlns:xf="http://www.w3.org/2002/xforms" bind="query">
               <xf:send submission="do-search" ev:event="xforms-value-changed"/>
          </xf:input>
          <xf:submit submission="do-search">
              <xf:label>
                  <img alt="search" src="/share/icons/fugue-icons/icons/magnifier-medium-left.png" />
               </xf:label>
           </xf:submit>
            </span>
        </div>
        <div class="ui-layout-west">
            <div id="result">
                <ol>
                    <xf:repeat xmlns:xf="http://www.w3.org/2002/xforms" id="place_list" nodeset="instance('response')//*:place">
                        <li>
                            <xf:trigger appearance="minimal">
                                <xf:action xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="DOMActivate">
                                    <xf:setvalue bind="lon" value="instance('response')//*:place[index('place_list')]/@lon"></xf:setvalue>
                                    <xf:setvalue bind="lat" value="instance('response')//*:place[index('place_list')]/@lat"></xf:setvalue>
                                    <xf:setvalue bind="icon" value="instance('response')//*:place[index('place_list')]/@icon"></xf:setvalue>
                                    <xf:load>
                                        <xf:resource value="instance('locate')"></xf:resource>
                                    </xf:load>

                                </xf:action>
                                <xf:label>
                                    <xf:output ref="@icon" mediatype="image/*" if="@icon"></xf:output>
                                    <xf:output ref="@display_name"></xf:output>
                                </xf:label>
                            </xf:trigger>
                        </li>
                    </xf:repeat>
                </ol>
            </div>
        </div>
        <div class="ui-layout-center">
            <div id="map"></div>
        </div>
        <div div="#debug" class="ui-layout-south">
            <div id="console"></div>
        </div>
    </body>

以下是伺服器端 XQuery 程式碼的示例。

   geo:search($query, $min-lon, $min-lat, $max-lon, $max-lat)

將在伺服器端針對例項進行評估

<geo:search>
     <param:query/>
     <param:min-lon/>
     <param:min-lat/>
     <param:max-lon/>
     <param:max-lat/>
</geo:search>

Geo XQuery 模組

[編輯 | 編輯原始碼]
module namespace geo = "http://schematronic.ru/geo";

import module namespace http    = "http://exist-db.org/xquery/httpclient";
import module namespace request = "http://exist-db.org/xquery/request";

declare variable $geo:search-service-uri := "http://nominatim.openstreetmap.org/search";

declare function geo:search($query  as xs:string,
                           $min-lon as xs:float, $min-lat as xs:float,
                           $max-lon as xs:float, $max-lat as xs:float) {

   let $view-box := string-join(($min-lon, $min-lat, $max-lon, $max-lat), ",")
   let $lon      := ($min-lon + $max-lon) div 2
   let $lat      := ($min-lat + $max-lat) div 2
   let $uri      := escape-uri(xs:anyURI(concat(
                       $geo:search-service-uri,
                       "?format=xml",
                       "&amp;viewbox=", $view-box,
                       "&amp;addressdetails=1&amp;limit=100",
                       "&amp;polygon=0",
                       "&amp;q=", $query
                    )), false())
   let $response := http:get($uri, false(), ())

   let $results  := $response//searchresults

   return
       element {name($results)} {
           $response/@*,
           for $i in $results/place
           order by ($lon - $i/@lon) * ($lon - $i/@lon) + ($lat - $i/@lat) * ($lat - $i/@lat)
           return $i
       }

};

declare function geo:search($query as xs:string, $view-box as xs:float*) {
   geo:search($query, $view-box[1], $view-box[2], $view-box[3], $view-box[4])
};

declare function geo:search($query as xs:string) {
   geo:search($query, -180, -90, 180, 90)
};

所有工作均由 Evgeny Gazdovsky 完成。文稿由 Dan McCreary 完成。

華夏公益教科書