Jak płynnie powiększyć znacznik w Google Maps?

Chciałbym móc płynnie powiększać znacznik w Google Maps. Jeśli po prostu ustawisz zoom po dwukrotnym kliknięciu, Mapa nagle znajduje się na tym poziomie powiększenia, bez płynnego przejścia.

Powiększając tylko jeden poziom dalej niż obecny poziom, Google Maps pokazuje ładne płynne przejście. Więc musi być możliwe płynne przybliżenie więcej niż jednego poziomu,ale jak?

Author: PeanutButterJelly, 2011-01-20

6 answers

Na szczęście, chciałem osiągnąć ten sam efekt Ostatnio, i znalazłem rozwiązanie, które zrobiłem post o. Zasadniczo samo ustawienie limitu czasu dla każdego przejścia nie wystarczy, ponieważ może to łatwo spowodować "start-stop" rodzaj powiększenia, jeśli efekt powiększenia Google nie jest jeszcze gotowy lub już dawno zakończył.

Jak wspomniał Martin, są w tym pewne wady, których Nie będę powtarzał. To, czy w końcu tego użyjesz, jest twoim wyborem i zależy w dużej mierze od moc procesora użytkownika i / lub przeglądarki. Jest to jednak ładny efekt i na pewno zaimponuje niektórym, gdy są mądrze używane.

Moje rozwiązanie było następujące:

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

Zasadniczo sprowadza się to do dostosowania poziomu powiększenia o jeden, nasłuchiwania zdarzenia zoom_changed, oczekiwania 80ms przed ponownym dostosowaniem poziomu powiększenia o jeden, itp. Fajne w tym jest to, że wydarzenie zoom_changed wydaje się być nazywane po płynnym przejściu przez Google Maps, ale przed rzeczywiste obrazy są załadowany, więc nie marnuje zbytnio przepustowości.

80ms w timeout to również magiczna liczba, którą wymyśliłem - dobrze byłoby zrobić dokładniejszy test i zobaczyć, co działa na różnych systemach i przeglądarkach, a być może zmienić algorytm nieco w oparciu o swoje ustalenia lub dla różnych systemów.

Prawdopodobnie nie jest też konieczne dodawanie i usuwanie słuchacza za każdym razem, ale możesz sam dokonać tej niewielkiej poprawy, jeśli chcesz.

 52
Author: Herman Schaaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-28 03:28:32

Ten mi ładnie zadziałał:

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);
    }
}
 8
Author: Igor Mukhin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 21:03:35

Możesz spróbować użyć setInterval, aby powiększyć jeden poziom na raz i wyczyścić go, gdy osiągniesz pożądany poziom.

Problem polega na tym, że interwał, który sprawi, że będzie działać, jest całkowicie zależny od cpu i przepustowości maszyny użytkowników (jak szybko może załadować i renderować nowy zestaw płytek obrazu).

Tbh, nie jestem pewien, czy da się to zrobić tak, aby działało świetnie w każdej sytuacji, ale mały odstęp między poziomami zoomu może trochę pomóc.

Kilka rzeczy o których warto pamiętać:

    To znacznie bardziej obciąży procesor i przepustowość użytkowników niż przejście bezpośrednio do wybranego poziomu zoomlevel]}
  1. użytkownik będzie musiał poczekać, aż zostanie to zrobione, aby rozpocząć interakcję z mapą, co może łatwo stać się bardzo złym doświadczeniem dla użytkownika.

Te dwa i prawdopodobnie inne powody są powodem, dla którego google nie zbudowało takiego zoomu, jaki chcesz na mapach - bo to zły pomysł...

 2
Author: Martin Jespersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-20 20:49:54

@ Herman Schaaf Twoje rozwiązanie jest świetne, ale po dwukrotnym kliknięciu pomija kilka powiększeń :D Więc zrobiłem rozwiązanie + smoothZoom out Nie mogę wziąć całego uznania, że edytowałem kod JesseDobbelaere ' a z jsfiddle.net To mieszanka Twojego i Jesse ' ego.

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

Zrobiłem jeszcze kilka zmiennych, takich jak timeOut i maxZoomIn Out... Pełny kod znajdziesz na jsfiddle http://jsfiddle.net/dexy86/9afy9/

 2
Author: Dexy86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-15 06:18:36

Próbowałem alternatyw podanych powyżej, jednak za każdym razem, gdy widzę Przejście W przeglądarce komputerowej lub aplikacji mobilnej, wszystko następuje natychmiast, lub przynajmniej w okresie czasu, który jest niedostrzegalny dla oka ze względu na czas między każdą iteracją pętli, przynajmniej na sprzęcie, na którym testowałem.

Użyłem tej samej pętli co inne metody, ale zmieniłem timeout tak, że zoom pojawiał się szybciej, gdy poziom zoomu był wyższy, i wolniej, gdy był niższy, więc wyniki były bardziej widoczne.

Zamiast używać stałego timeout period, ustawiam pierwszy timeout na 0, a następnie kolejne timeouty na następujące szybkie i brudne równanie

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

W kodzie założyłem maksymalny zoom jako 18, ale możesz użyć maxZoom , aby dowiedzieć się, jaki jest poziom zoomu dla danej lat/long. Mój kod to:

timeout = (1+map.getZoom() / 18) * 500;
 0
Author: Debs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-24 01:33:25

Spowoduje płynne powiększenie żądanej lokalizacji. Spróbuj dodać te linie:

LatLng latLng = new LatLng(lat,lng);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_FACTOR));
 -1
Author: Chaman Saini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 08:24:33