wiki:oid/WorkLog/09-02-04

Version 8 (modified by jazz, 15 years ago) (diff)

--

2009-02-04

  • 原本 waue 發表的Google Map的網址模組轉換,在官方的名稱為 Google Mapplets API
  • Google Mapplet API 跟 Google Map API 最主要的差別在於 Mapplet 是在官方 Google Map 上呈現,而 Google Map API 則可以用在自己的網站上。
    The main difference is that Mapplets run on Google Maps, 
    while the traditional Maps API is used to create maps on other websites.
    
  • "赤壁"原始碼 - http://code.google.com/p/redcliff/source/checkout
    svn checkout http://redcliff.googlecode.com/svn/trunk/ redcliff-read-only
    
  • 赤壁的 Mapplet

  • 在原始碼中,people.json 是用來顯示"主要人物"這個 Tag 的資料來源

  • 在原始碼中,big_event.json 是用來顯示"歷史事件"這個 Tag 的資料來源

  • 在原始碼中,event.json 是用來顯示點選"歷史事件"其中一個事件後,顯示各事件的關連資料來源

  • 在原始碼中,location.json 是用來把歷史古城的位置用貼圖方式顯示的經緯度資料來源

  • 在原始碼中,element.json 是用在點選特定古城位置時,顯示關聯事件的資料來源

  • 赤壁 Mapplet 原始碼 XML 解析
    <?xml version="1.0" encoding="UTF-8"?>
    <Module>
    
    <ModulePrefs title="赤壁之戰"
                 description="赤壁之戰的歷史地圖"
                 author="Google Redcliff Team"
                 author_email="chibi.ditu@gmail.com">
    # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/mapplets/basics.html#Loading_the_Mapplets_API
    # 必須加入 sharedmap  feature 才能讓 mapplet 載入定義在 Content 中的 javascript 程式
       <Require feature="sharedmap"/>
       <Require feature="dynamic-height" />
       <Require feature="analytics" />
    </ModulePrefs>
    <Content type="html"><![CDATA[
    <style>@CHARSET "UTF-8";
    ### 以下略過 CSS 定義 ###
    </style>
    <!-- Show this gif when loading -->
    # 初始化的時候顯示"正在讀取..."的圖示跟字樣
    <div id="loading" style="color:#AAA;text-align:center;margin-top:40px;font-size:12px;"><img src="http://www.google.cn/staticcn/chibi/pie_32.gif"><br><br>正在讀取...</div>
    
  • 底下先定義 DOM 元件
    # 初始之後要顯示的 DIV 元件
    <!-- Hide first when loading -->
    <div id="main" style="z-index:10;display:none;">
       <div class="top-div">
         <span>選擇地圖: </span>
         <select class="dropdown-box" id="select_tiles">
           <option value="1.0">歷史地圖</option>
           <option value="0.5">混合地圖</option>
           <option value="0.0">現代地圖</option>
         </select>
       </div>
    
  • 上面這段就是畫面上的下拉式選單

   <div class="tab-content" id="tabContent">
     <div class="tab-head">
           <div class="tab-inactive"><div id="events_tab">歷史事件</div></div>
           <div class="tab-active"><div id="characters_tab">主要人物</div></div>
           <div class="tab-inactive"><div id="vote_tab">投票</div></div>
     </div>
  • 分頁 -
         <div id="events_cnt" style="display:none;">
           <div id="unused_bar"><!-- TODO may need to add some text in this bar --></div>
           <div id="big_event_list" ></div>
         </div>
    
  • 歷史事件 (events_cnt) 預設隱藏,裡面包含 big_event_list 元件
         <div id="characters_cnt">
           <div id="kingdom_checkbox">
             <label for="checkbox_wei">曹操軍</label><input id="checkbox_wei" type="checkbox" checked>
             <label for="checkbox_wu">孫權軍</label><input id="checkbox_wu" type="checkbox" checked>
             <label for="checkbox_shu">劉備軍</label><input id="checkbox_shu" type="checkbox" checked>
           </div>
           <div id="character_list"></div>
         </div>
    
  • 上方三個 checkbox ,底下是 character_list 用來顯示內容
         <div id="vote_cnt" style="display:none;">
           <div id="unused_bar"></div>
           <iframe frameborder=0 class="vote-ifr" src="http://redcliffvotetw.appspot.com/?locale=zh_tw"></iframe>
         </div>
       </div>
    
  • 投票 vote_cnt 預設隱藏,用 iframe 帶入 http://redcliffvotetw.appspot.com/?locale=zh_tw 這個 Google App Engine 的內容
       <div class="bottom-button-div">
         <a href='#' id="clear_button">清除地圖上的標誌</a>
         <span id="share_button"></span>
       </div>
       <div class="bottom-button-div2">
         <a href="#" id="disclaimer_show">聲明</a>
         <div id="disclaimer_box" style="display:none;"><div>
              本地圖為Google Inc.製作。赤壁之戰地圖中所使用的各種數據,為參考《後漢書》、《三國志》、《資治通鑑》、《三國郡縣表》等書籍資料,以及<a target="_blank" href= "http://zh.wikipedia.org/w/index.php?title=%E9%A6%96%E9%A1%B5&variant=zh-tw/">維基百科</a>等網站,整理獲得。
              人物肖像,事件相片等,為<a target="_blank" href="http://www.foxmovies.com.tw/">美商二十世紀福斯影片公司</a>及<a target="_blank" href="http://www.meiah.com/">美亞娛樂資訊集團有限公司</a>授權使用之電影《赤壁》劇照。
               <br><br>
              聯繫我們: <a href="mailto:chibi.ditu@gmail.com">chibi.ditu@gmail.com</a>
               <br>
               <span id="disclaimer_close">關閉</span>
             </div></div>
       </div>
    </div>
    
  • 主要顯示三個元件,包括"分享給朋友"、"清除地圖上的標誌"、"聲明"
  • 點選"聲明"才會顯示 disclaimer_box 的畫面
    <div style="height:2em;"></div>
    <script src="http://www.google.com/jsapi" type="text/javascript"></script>
    <script type="text/javascript">
             google.load("jquery", "1.2.6");
    </script>
    
  • 上面這一段是宣告要載入 Hosting 在 Google 的 jQuery API 1.2.6 版
    <script type="text/javascript">
    window.serverBase="http://www.google.com";
    ### 略過 - 這段看不太懂因為中文字轉碼過了應該是在用來做定義 "分享給朋友" 的寄信行為!!
    share.SharingButton=share.SharingWidget;
     })();
    </script>
    
  • [註] 底下開始會稍微變動一下原始碼的順序,我們先來看 jQuery 的 main 進入點
      $(function(){
        G_MAP = new RedcliffMap(); # 呼叫 RedcliffMap() 產生 GMap2 物件
        LoadLocation();            # 呼叫 LoadLocation()  location.json 讀檔並畫出歷史古城的位置點
        new TilesSelect();
        new TabManager(['events', 'characters', 'vote'], 'characters');
        new Disclaimer();
        $('#clear_button').click(function(){
          G_MAP.clearOverlays();
        });
        new CharacterFilter();
        _IG_Analytics(UAACCT, "/view/load");
      });
    
  • 關於 G_MAP = new RedcliffMap(); 這行程式
      ### 首先要看的是 RedcliffMap 這個類別物件的建構子(Constructor)
      ### 以下省略類別中的 method 函數定義,從這裡可以看到 RedcliffMap 定義了 9 個 method
    
      ##############################################################################
      ### 其中 addOverlay 跟 removeOverlay 應該就是我們想要找的顯示/隱藏不同圖層的實作方法 ###
      ##############################################################################
    
      RedcliffMap.prototype = {
        changeTiles: function(opacity_val),
        addOverlay: function(overlay),
        removeOverlay: function(overlay),
        openInfoWindow: function(type, id, latlng),
        highLightOverlay: function(element_ids),
        deHighLightOverlay: function(),
        setCenter: function(center, level),
        clearOverlays: function(),
        updateOverlay: function(type, id)
      };
    
      function RedcliffMap(node) {
        var me = this;
    
        # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/mapplets/basics.html#GMap2
        # GMap2 代表 Google Map 的 map 根元件
        this.gmap = new GMap2();
    
        # 設定初始地圖中心經緯度位置
        this.gmap.setCenter(new GLatLng(29.833, 113.618), 7, G_PHYSICAL_MAP);
    
        # 用 GTileLayerOverlay 來取代原始的地圖底圖
        # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/overlays.html#Tile_Overlays
        # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/reference.html#GTileLayerOverlay
        # 建構子定義 GTileLayerOverlay(tileLayer:GTileLayer, opts?:GTileLayerOverlayOptions) 
    
        this.tileLayerOverlay = new GTileLayerOverlay(
    
        # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/reference.html#GTileLayer
        # 建構子定義 GTileLayer(copyrights:GCopyrightCollection, minResolution:Number, 
        #                     maxResolution:Number, options?:GTileLayerOptions) 
        # 參考 http://code.google.com/intl/zh-TW/apis/maps/documentation/reference.html#GTileLayerOptions
        # 這裡設定 tileUrlTemplate: URL.tile_url = http://mt.google.cn/mt?v=cnsg1.2&hl=zh-CN&x={X}&y={Y}&z={Z}
        # 根據 API 文件 Templates 必須是這樣: http://host/tile?x={X}&y={Y}&z={Z}.png 
    
          new GTileLayer(null, null, null, {
            tileUrlTemplate: URL.tile_url,
            isPng:true,
            opacity:1.0
          })
        );
        this.gmap.addOverlay(this.tileLayerOverlay); 
      };
    
  • 關於 LoadLocation(); 這行程式
      function LoadLocation() {
    
        ### 參考 http://code.google.com/intl/zh-TW/apis/gadgets/docs/legacy/remote-content.html#Fetch_text
        ### _IG_FetchContent(url, func) 是一個 Mapplet 的 callback 函數,用來定義擷取 url 之後該執行哪個 func 函數
    
        ### 這裡定義要去擷取 URL.location_url ,
        ### 也就是 http://redcliff.googlecode.com/svn/trunk/data_tc/location.json?bpc=12191314
        ### [備註] 加上 bpc= 是為了清除 google code 的 cache ,這點在程式碼裡面也有寫上註解
        ### <!-- NOTE: Add "?bpc=<radnom>" to by pass the cache for the css file. -->
    
        _IG_FetchContent(URL.location_url, function(data) {
    
        ### 宣告 json 變數等於 callback 函數回傳回來的 data
        ### 參考 http://www.w3schools.com/jsref/jsref_eval.asp
    
        ### location.json 裡的內容
        ### [ {"name" : "成都" , "lat" : 30.670992 , "lng" : 104.067993 }, ... ]
    
          var json = eval(data);
    
        ### 依序把 location.json 裡的 name 跟 location (lat,lng) 設定上去
    
          $.each(json, function(index, location) {
    
        ### var LOCATION = new Hash(); 這裡的 LOCATION 物件是一個 Hash (湊雜)
        ### Hash 類別必須參考原始碼中 Hash.prototype 定義了 5 個 method
        ### removeItem(in_key), getItem(in_key), setItem(in_key, in_value), hasItem(in_key), getLength()
        ### 還有 length 跟 item 兩個 field.
        ### 照 setItem(in_key, in_value) 語法看起來應該會產生一個 二維陣列 (Array)
    
        ### 這裡還呼叫了 Location 建構子
        ### function Location(raw_location) {
        ###   var me = this;
        ###   this.location = raw_location;
        ###   this.name = location.name;
        ###   this.point = new GLatLng(raw_location.lat, raw_location.lng);
        ### };
    
        ### 因此這一行的最後結果應該是
        ### Location.item=[{"成都",GLatLng(30.670992,104.067993)},{...}] 這樣一個二維陣列
    
            LOCATION.setItem(location.name, new Location(location));
          });
        ### 呼叫 LoadElement() 跟 LoadEvent()
          LoadElement();
          LoadEvent();
        });
      };
    
  • 從 Element 的 prototype 跟建構子看來,Element 類別包含 id, element, type, event 四個 field,getHiddenPolylineOverlay(points, weigth, id)、getArrowGroundOverlay(arrow_url, sw, ne)、getMarker(icon_url, point, id) 三個暫時的 inner function,drawOnMap()、removeFromMap()兩個 method (其他被註解掉了)
      function Element(raw_element) {
        var me = this;
        this.id = raw_element.id
        this.element = raw_element;
        this.type = raw_element.type;
        
        var getHiddenPolylineOverlay = function(points, weigth, id) {
          var latlngs = new Array();
          $.each(points, function(index, point){
            latlngs.push(new GLatLng(point.lat, point.lng));
          });
          var polyline = new GPolygon(latlngs, "#000000", 10, 0.0);
          GEvent.addListener(polyline, 'click', function(latlng) {
            G_MAP.openInfoWindow("ELEMENT", id, latlng);
          });
          return polyline;
        };
        
        var getArrowGroundOverlay = function(arrow_url, sw, ne) {
          var bound = new GLatLngBounds(new GLatLng(ne.lat, ne.lng), new GLatLng(sw.lat, sw.lng));
          var arrow = new GGroundOverlay(CN_BASE + 'arrow/'  + arrow_url + '.png', bound);
          return arrow;
        }
        
        var getMarker = function(icon_url, point, id) {
          var image = CN_BASE + 'icon/' + icon_url + '.png';
          var icon = new GIcon(G_DEFAULT_ICON, image);
          if (icon_url.length == 2)
            icon.iconSize = new GSize(45,32);
          else
            icon.iconSize = new GSize(25,32);
          var marker = new GMarker(point, {icon:icon});
          GEvent.addListener(marker, 'click', function() {
            G_MAP.openInfoWindow("ELEMENT", id, point);
          });
          return marker;
        }
        if (this.type == 'point') {
          this.point = new GLatLng(raw_element.lat, raw_element.lng);
          this.marker = getMarker(raw_element.pic, this.point, this.id);
        } else {
          this.hidden_polyline = getHiddenPolylineOverlay(raw_element.hot_points, C_POLYLINE_WEIGHT, this.id);
          this.arrow = getArrowGroundOverlay(raw_element.arrow, raw_element.arrow_points[0], raw_element.arrow_points[1]);
          
        } 
        this.events = raw_element.event_ids;
      };
      
      Element.prototype = {
        drawOnMap: function() {
          if (this.type == 'line') {
            G_MAP.addOverlay(this.hidden_polyline);
            G_MAP.addOverlay(this.arrow);
          } else {
            G_MAP.addOverlay(this.marker);
          }
        },
        
        removeFromMap: function() {
          if (this.type == 'line') {
            G_MAP.removeOverlay(this.hidden_polyline);
            G_MAP.removeOverlay(this.arrow);
          } else {
            G_MAP.removeOverlay(this.marker);
          }
        }
        
        /*
        highLight: function() {
          G_MAP.removeOverlay(this.current_overlay);
          G_MAP.addOverlay(this.highlight_overlay);
          this.current_overlay = this.highlight_overlay;
        },
        
        deHighLight: function() {
          G_MAP.removeOverlay(this.current_overlay);
          G_MAP.addOverlay(this.overlay);
          this.current_overlay = this.overlay;
        },
        
        adjustZoomLevel: function() {
        }
        */
      };
    

Attachments (14)

Download all attachments as: .zip