2011-09-07 17 views
7

Google Maps v3 API'sı ile çalışıyorum ve ImageMapType sınıfını temel alan özel bir katman katmanım var. Bindirmenin karoları yüklenirken bir çeşit yükleme göstergesi göstermek istiyorum, ancak bittiğinde bilmenin bir yolunu görmüyorum.Google Maps v3: Bir ImageMapType yer paylaşımının döşemesinin ne zaman tamamlandığını nasıl anlarsınız?

bindirme oluşturmak için kod aşağıdaki benzer:

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

myMap.overlayMapTypes.push(myOverlay); 

yukarıdaki eserler sadece iyi ve bindirme başarıyla yükler; Sadece MapMapType yer paylaşımının durumuyla ilgili hiçbir şey belirtmek için harita tarafından hiçbir olay yayılmamış gibi görünüyor.

Haritaların fayanslar dolduğunda en azından bir "boşta" olayı olmasını beklerdim, ancak söyleyebildiğim kadarıyla.

ImageMapType yer paylaşımının ne zaman biteceğini nasıl bilebilirim?

DÜZENLEME Ben jsFiddle üzerinde bir test vakası yazdı: http://jsfiddle.net/6yvcB/ - kelime için konsol çıkışını İzle boştayken olay yangınları görmek için "boşta". Bir bindirme eklemek için düğmeyi tıkladığınızda asla ateşlemeyeceğine dikkat edin. Aynı zamanda, yavru kedi.

cevap

10
Orada bir ImageMapType bindirme yüklenmesi tamamlandıktan sonra bilmek hayır "kutunun dışında" yol, ama üzerinde kendi özel olay eklemek başardı Google Maps API v3 Forums üzerinde suggestion from Martin sayesinde yayılması anlamına gelirdi

zaman katman yüklenmeyi bitirir.

temel yaklaşım şudur: Biz "Onload" Olay dinleyicileri ekleyebilmeniz için

  • İstenen URL her zaman,) bekleyen URL'lerin listesine
  • geçersiz kılma ImageMapType.getTile (URL eklemek Her <img> öğeye.
  • Her resmin "yükleme" olayı patladığında, söz konusu resmi bekleyen URL'ler listesinden kaldırın.
  • Bekleyen URL'lerin listesi boş olduğunda, özel "yer paylaşımlı reklam" etkinliğimizi yayar.

ben kuşaklar için aşağıdaki kodu kopyaladıktan ama jsFiddle üzerinde eylem görebilirsiniz: @ David tarafından yanıta dayalı 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

Harika çözüm için teşekkürler! – mfras3r

0

, ben saf JavaScript alternatif oluşturduk (Özellikle Op'un jQuery'yi belirtmediğini dikkate alarak).

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; 
    }; 
} 

Ve bu işlevler kolayca herhangi getTileUrl işlevinden çağrılabilir.

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); 

Bonus özellikler: çoklu katmanlar ve zaman aşımları için destek (sunucunun yavaş veya özensiz olması durumunda).

+0

Bu sürümde gözlemlediğim tek sorun, fayans zaten önbellekte olduğunda, onload olayının tetiklenmemiş olmasıdır.Çözüm, src parametresinden önce (http://stackoverflow.com/a/12355031/1816603) onload olayını ayarlamak olmalıdır, ancak bunun görüntü olarak getTile yöntemini geçersiz kılma yaklaşımıyla uyumlu olup olmadığından emin değilim. src, Haritalar kodunda ayarlanır. –

İlgili konular