2011-01-20 152 views
27

我希望能夠順利放大Google地圖中的標記。如果只需雙擊設置縮放,則地圖突然在該縮放級別上,沒有任何平滑過渡。如何在Google地圖上順利放大標記?

僅縮放比當前級別更高的一個級別,Google地圖顯示一個很好的平滑過渡。所以它必須能夠平滑地放大多於一個等級,但是怎麼樣?

回答

46

由於幸運的是,我最近想達到同樣的效果,並找到了一個解決方案,我做了a post。基本上,只爲每個轉換設置一個超時是不夠的,因爲如果Google的縮放效果還沒有完成,或者很長時間完成,它可能很容易導致「開始 - 停止」類型的縮放。

正如馬丁所說,這有一些缺點,我不會重申。最終是否使用此選項是您的選擇,並且很大程度上取決於用戶的CPU功率和/或瀏覽器。這是一個很好的效果,但一定要打動一些,如果明智地使用。

我的解決辦法如下:

// example marker: 
var marker = new google.maps.Marker({ 
    map: map, 
    position: new google.maps.LatLng(-20.3,30.3) 
}); 


// add the double-click event listener 
google.maps.event.addListener(marker, 'dblclick', function(event){ 
    map = marker.getMap();  
    map.setCenter(overlay.getPosition()); // set map center to marker position 
    smoothZoom(map, 12, map.getZoom()); // call smoothZoom, parameters map, final zoomLevel, and starting zoom level 
}); 


// the smooth zoom function 
function smoothZoom (map, max, cnt) { 
    if (cnt >= max) { 
     return; 
    } 
    else { 
     z = google.maps.event.addListener(map, 'zoom_changed', function(event){ 
      google.maps.event.removeListener(z); 
      smoothZoom(map, max, cnt + 1); 
     }); 
     setTimeout(function(){map.setZoom(cnt)}, 80); // 80ms is what I found to work well on my system -- it might not work well on all systems 
    } 
} 

基本上它歸結爲是由一個調整縮放級別,監聽zoom_changed事件,通過一個重新調整縮放級別之前等待80毫秒,等等。好的是,zoom_changed事件好像是在谷歌地圖提供的平滑過渡之後調用的,但之前的實際的圖片被加載,所以它不會浪費帶寬太多。

超時時間的80ms也是我想出來的一個幻數 - 你會被建議做一個更徹底的測試,看看在不同的系統和瀏覽器上有什麼作用,並且可能會根據你的發現或不同系統。

這可能也沒有必要每次都添加和刪除監聽器,但如果您願意的話,您可以自己做出一點改進。

+0

謝謝,我會看看! – PeanutButterJelly 2011-01-20 21:14:31

+4

工程就像一個魅力!而不是setCenter,如果你使用panTo它看起來更好......;) – 2012-07-17 11:36:44

2

您可以嘗試使用setInterval一次放大一個級別,並在達到所需級別時將其清除。

這樣做的問題是,使其工作的間隔完全取決於用戶機器的cpu和帶寬(它可以以多快的速度加載和渲染新的圖像切片集)。

Tbh,我不知道它可以做到這一點,以便它在任何情況下都能很好地工作,但縮放級別之間的小間隔可能會有所幫助。

有幾件事情要記住壽:

  1. 這將會把很多更加註重用戶的CPU和帶寬比直接到選定的縮放級別
  2. 用戶將不得不等待,直到這個完成開始與地圖交互,這可能很容易成爲一個非常糟糕的用戶體驗。

這兩個和其他可能的原因是,爲什麼谷歌沒有建立你想的那種放大到地圖擺在首位 - 因爲它是一個糟糕的主意......

+0

是的,我明白了你的觀點 - 我會記住這一點。它用於內部環境,所以CPU和帶寬是已知的變量,不應該是一個問題。至於轉換的時間 - 只要用戶不需要太頻繁,它應該沒問題。事實上,雙擊標記後不會完全迷失方向會很好。 – PeanutButterJelly 2011-01-20 21:14:06

1

@Herman沙夫 您的解決方案是偉大的,但是當你雙擊它跳過幾個變焦 :d 所以我做了一個解決方案+ smoothZoom出 我不能把所有我從編輯JesseDobbelaere代碼信貸jsfiddle.net 這是你和Jesse的代碼的組合。

function smoothZoom(map, level, cnt, mode) 
{ 
    if(mode == true) 
    { 
     if (cnt >= level) { 
      return; 
     } 
     else 
     { 
      if((maxZoomOut + 2) <= cnt) 
      { 
       var z = google.maps.event.addListener(map, 'zoom_changed', function(event) 
       { 
        google.maps.event.removeListener(z); 
        map.setCenter(marker.getPosition()); 
        smoothZoom(map, level, cnt + 1, true); 
       }); 
       setTimeout(function(){map.setZoom(cnt);}, timeOut); 
      } 
      else 
      { 
       map.setZoom(cnt); 
       smoothZoom(map, level, cnt + 1, true); 
      } 
     } 
    } 
    else 
    { 
     if (cnt < level) { 
      return; 
     } 
     else 
     { 
      var z = google.maps.event.addListener(map, 'zoom_changed', function(event) 
      { 
       google.maps.event.removeListener(z); 
       map.setCenter(marker.getPosition()); 
       smoothZoom(map, level, cnt - 1, false); 
      }); 
      if(maxZoomIn - 2 <= cnt) 
      { 
       map.setZoom(cnt); 
      } 
      else 
      { 
       setTimeout(function(){map.setZoom(cnt);}, timeOut); 
      } 
     } 
    } 
}  

我做了幾樣超時和maxZoomIn了... 多個變量,你可以找到的jsfiddle http://jsfiddle.net/dexy86/9afy9/

-2

這將順利放大所需的位置全部代碼。嘗試添加這些行:

LatLng latLng = new LatLng(lat,lng); 
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_FACTOR)); 
8

這一個很好的工作對我來說:

function animateMapZoomTo(map, targetZoom) { 
    var currentZoom = arguments[2] || map.getZoom(); 
    if (currentZoom != targetZoom) { 
     google.maps.event.addListenerOnce(map, 'zoom_changed', function (event) { 
      animateMapZoomTo(map, targetZoom, currentZoom + (targetZoom > currentZoom ? 1 : -1)); 
     }); 
     setTimeout(function(){ map.setZoom(currentZoom) }, 80); 
    } 
} 
0

我已經試過不過上面提供的方案,每當我在桌面瀏覽器或移動應用視圖的轉換,這一切都會立即或至少在一段時間內發生,這段時間由於每次循環迭代之間的時間而至少在我試用過的硬件上是不可感知的。

我使用了與其他方法相同的循環,但更改了超時時間,以便縮放級別越高,變焦速度越慢,變慢時越慢,因此結果更加明顯。

不是採用固定的超時時間,我第一超時設置爲0,隨後的超時下面的快速和骯髒的方程

((1+ currentZoom)/maxZoom) * 500; 

在代碼中,我認爲最大變焦爲18,但你可以使用maxZoom來查找給定緯度/經度的縮放級別。我的代碼是:

timeout = (1+map.getZoom()/18) * 500;