2011-09-07 18 views
7

私はGoogle Maps v3 APIを使用しています.ImageMapTypeクラスに基づいてカスタムオーバーレイレイヤーを使用しています。オーバーレイのタイルがロードされている間、ある種のローディングインジケータを表示したいと思いますが、完了した時点を知る方法はありません。Google Maps v3:ImageMapTypeオーバーレイのタイルの読み込みが完了したときを確認するにはどうすればよいですか?

オーバーレイを作成するコードは次のようになります。

var myOverlay = new google.maps.ImageMapType({ 
    getTileUrl: myGetTileUrl, 
    tileSize: new google.maps.Size(256, 256), 
    isPng: true 
}); 

myMap.overlayMapTypes.push(myOverlay); 

上記の作品をうまくし、オーバーレイが正常にロードします。 ImageMapTypeオーバーレイのステータスについて何かを示すために、マップによってイベントが送出されないように見えるだけです。

タイルのロードが完了すると、地図に少なくとも「アイドル」イベントが発生することが予想されます。

ImageMapTypeオーバーレイの読み込みが完了したらどうすればわかりますか?

EDIT

私はjsFiddle上のテストケースを書いた:http://jsfiddle.net/6yvcB/ - アイドル時にイベントが発生見るために、「アイドル」という言葉のためにあなたのコンソール出力を監視します。オーバーレイを追加するためにボタンをクリックすると、決して起動しないことに注意してください。

また、子猫も。

答えて

10

ImageMapTypeオーバーレイの読み込みが完了したときを知るための「すぐに使える」方法はないようですが、Google Maps API v3 Forumssuggestion from Martinのおかげで、自分のカスタムイベントを追加することができました。層の装填が完了する。

基本的なアプローチは次のとおりです。

  • URLが要求されるたびに、我々は「オンロード」イベントリスナーを追加できるように、保留中のURL
  • オーバーライドImageMapType.getTile()のリストにURLを追加それぞれ<img>要素。
  • 各画像の「ロード」イベントが発生すると、その画像を保留中のURLのリストから削除します。
  • 保留中のURLのリストが空の場合、カスタムの「overlay-idle」イベントを発行します。

私は後世のために以下のコードをコピーしましたが、あなたはjsFiddle上のアクションでそれを見ることができます:@デビッドによる応答に基づいてhttp://jsfiddle.net/6yvcB/22/

// Create a base map 
var options = { 
    zoom: 3, 
    center: new google.maps.LatLng(37.59, -99.13), 
    mapTypeId: "terrain" 
}; 
var map = new google.maps.Map($("#map")[0], options); 

// Listen for the map to emit "idle" events 
google.maps.event.addListener(map, "idle", function(){ 
    console.log("map is idle"); 
}); 

// Keep track of pending tile requests 
var pendingUrls = []; 

$("#btn").click(function() { 
    var index = 0; 
    var urls = [ "http://placekitten.com/256/256", 
       "http://placekitten.com/g/256/256", 
       "http://placekitten.com/255/255", 
       "http://placekitten.com/g/255/255", 
       "http://placekitten.com/257/257", 
       "http://placekitten.com/g/257/257" ]; 

    var overlay = new google.maps.ImageMapType({ 
     getTileUrl: function() { 
      var url = urls[index % urls.length]; 
      index++; 

      // Add this url to our list of pending urls 
      pendingUrls.push(url); 

      // if this is our first pending tile, signal that we just became busy 
      if (pendingUrls.length === 1) { 
       $(overlay).trigger("overlay-busy"); 
      } 

      return url; 
     }, 
     tileSize: new google.maps.Size(256, 256), 
     isPng: true, 
     opacity: 0.60 
    }); 

    // Listen for our custom events 
    $(overlay).bind("overlay-idle", function() { 
     console.log("overlay is idle"); 
    }); 

    $(overlay).bind("overlay-busy", function() { 
     console.log("overlay is busy"); 
    }); 


    // Copy the original getTile function so we can override it, 
    // but still make use of the original function 
    overlay.baseGetTile = overlay.getTile; 

    // Override getTile so we may add event listeners to know when the images load 
    overlay.getTile = function(tileCoord, zoom, ownerDocument) { 

     // Get the DOM node generated by the out-of-the-box ImageMapType 
     var node = overlay.baseGetTile(tileCoord, zoom, ownerDocument); 

     // Listen for any images within the node to finish loading 
     $("img", node).one("load", function() { 

      // Remove the image from our list of pending urls 
      var index = $.inArray(this.__src__, pendingUrls); 
      pendingUrls.splice(index, 1); 

      // If the pending url list is empty, emit an event to 
      // indicate that the tiles are finished loading 
      if (pendingUrls.length === 0) { 
       $(overlay).trigger("overlay-idle"); 
      } 
     }); 

     return node; 
    }; 

    map.overlayMapTypes.push(overlay); 
}); 
+1

すばらしいソリューションをありがとう! – mfras3r

0

、私は(純粋なJavascriptの代替を作成しましたOpにjQueryが指定されていないことを考慮して)。

var pendingUrls = []; 

function addPendingUrl(id, url) 
{ 
    // Add this url to our list of pending urls 
    pendingUrls[id].push(url); 

    //console.log("URL " + url + " added (" + pendingUrls[id].length + ")"); 

    // if this is our first pending tile, signal that we just became busy 
    if (pendingUrls[id].length === 1) { 
     console.log("overlay is busy"); 
    } 
} 

function addTileLoadListener(id, mapType, timeout) 
{ 
    // Initialise the sub-array for this particular id 
    pendingUrls[id] = []; 

    // Copy the original getTile function so we can override it, but still make use of the original function 
    mapType.baseGetTile = mapType.getTile; 

    // Override getTile so we may add event listeners to know when the images load 
    mapType.getTile = function(tileCoord, zoom, ownerDocument) 
    { 
     // Get the DOM node generated by the out-of-the-box ImageMapType 
     var node = mapType.baseGetTile(tileCoord, zoom, ownerDocument); 

     //console.log("URL " + node.firstChild.__src__ + " confirmed (" + pendingUrls[id].length + ")"); 

     function removePendingImg(node, src, result) 
     { 
      var index = pendingUrls[id].indexOf(src); 
      if (index == -1) 
      { 
       //console.log("URL " + src + " " + "not found" + " (" + pendingUrls[id].length + ")"); 
      } 
      else 
      { 
       pendingUrls[id].splice(index, 1); 
       //console.log("URL " + src + " " + result + " (" + pendingUrls[id].length + ")"); 

       // If the pending url list is empty, emit an event to indicate that the tiles are finished loading 
       if (pendingUrls[id].length === 0) { 
        console.log("overlay is idle"); 
       }     
      } 
     } 

     // Listen for any images within the node to finish loading 
     node.getElementsByTagName("img")[0].onload = function() { 
      //console.log("URL " + node.firstChild.src + " maybe loaded (" + node.firstChild.__src__ + ")"); 

      // Check that we have loaded the final image. We detect this because the node.src ends with what is in node.__src__ 
      var str = node.firstChild.src; 
      var suffix = node.firstChild.__src__; 
      if (str.indexOf(suffix, str.length - suffix.length) !== -1) 
      { 
       removePendingImg(node, node.firstChild.__src__, "loaded"); // Remove the image from our list of pending urls 
      } 
     }; 

     // Limit the wait 
     var imgsrc = node.firstChild.__src__; 
     setTimeout(function() { 
      if (node.firstChild) // if the map has already changed and the image is not going to be loaded, the node is destroyed 
      { 
       //var index = pendingUrls[id].indexOf(node.firstChild.__src__); 
       //if (index != -1) 

       // If the image is not loaded yet (node.src changes to the same value as node.firstChild.__src__ when loaded) 
       var str = node.firstChild.src; 
       var suffix = node.firstChild.__src__; 
       if (!(str.indexOf(suffix, str.length - suffix.length) !== -1)) 
       { 
        node.getElementsByTagName("img")[0].onload = null; // Disable the event handler for this node 
        removePendingImg(node, node.firstChild.__src__, "timed out"); // Remove the image from our list of pending urls 
       } 
      } 
      else removePendingImg(node, imgsrc, "discarded"); // Remove the image from our list of pending urls 
     }, timeout); 

     return node; 
    }; 
} 

そして、これらの機能は、簡単に任意のgetTileUrl関数から呼び出すことができます。

myMapType = new google.maps.ImageMapType({ 
    getTileUrl: function(coord, zoom) 
    { 
     var url = '//a.tile.server.com/' + zoom + '/' + coord.x + '/' + coord.y + '.png'; 

     // Add this url to our list of pending urls, and enable the loading image if appropriate 
     addPendingUrl("myLayer", url); 

     return url; 
    }, 
    tileSize: new google.maps.Size(256, 256), 
    opacity: 0.5 
}); 

// Listen for all the images having been loaded 
addTileLoadListener("myLayer", myMapType, 15000); 

ボーナス機能:複数の層およびタイムアウトのサポート(場合、サーバが遅いかずさんです)。

+0

このバージョンで私が観察した唯一の問題は、タイルがすでにキャッシュに入っているときにonloadイベントがトリガされないことです。解決策は、srcパラメータ(http://stackoverflow.com/a/12355031/1816603)の前にonloadイベントを設定する必要がありますが、イメージと同じgetTileメソッドをオーバーライドする方法と互換性があるかどうかはわかりませんsrcはMapsコードで設定されています。 –

関連する問題