Подтвердить что ты не робот

Как плавно масштабировать маркер в Картах Google?

Я хотел бы иметь возможность плавно масштабировать маркер в Картах Google. Если вы просто устанавливаете масштаб с двойным щелчком, карта внезапно переходит на этот уровень масштабирования без плавного перехода.

Увеличение только на один уровень, превышающий текущий уровень, Карты Google показывают приятный плавный переход. Таким образом, должно быть возможно плавное масштабирование для более чем одного уровня, но как?

4b9b3361

Ответ 1

Как повезло, я хотел добиться такого же эффекта в последнее время и нашел решение, которое я сделал сообщение. В принципе, просто установить тайм-аут для каждого перехода недостаточно, потому что это может легко привести к увеличению масштаба "старт-стоп", если эффект масштабирования Google еще не закончен или долго заканчивается.

Как упоминал Мартин, есть некоторые недостатки, которые я не буду повторять. Используете ли вы это в конце, это ваш выбор и во многом зависит от мощности вашего компьютера и/или браузера. Это приятный эффект, хотя и, несомненно, впечатляет некоторых, когда они используются с умом.

Мое решение было следующим:

// 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 похоже, вызывается после плавного перехода, предоставляемого Google Maps, но до того, как загружаются фактические изображения, поэтому он не слишком тратит трафик.

80 мс в тайм-ауте также является магическим числом, с которым я столкнулся - вам было бы полезно провести более тщательный тест и посмотреть, что работает в разных системах и браузерах, и, возможно, немного изменить алгоритм на основе ваших результатов или для разных систем.

Также не обязательно добавлять и удалять слушателя каждый раз, но вы можете сделать это небольшое улучшение самостоятельно, если хотите.

Ответ 2

Этот фильм работал у меня красиво:

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

Ответ 3

Вы можете попытаться использовать setInterval для увеличения одного уровня за раз и очистить его, когда достигнете желаемого уровня.

Проблема заключается в том, что интервал, который заставит его работать, полностью зависит от процессора и пропускной способности пользовательской машины (насколько быстро он может загружать и отображать новый набор фрагментов изображений).

Tbh, я не уверен, что это можно сделать так, чтобы он работал отлично в любой ситуации, но небольшой интервал между уровнями масштабирования может немного помочь.

Несколько вещей, которые следует иметь в виду:

  • это поставит намного больше внимания на процессор и пропускную способность пользователей, чем прямо на выбранный уровень масштабирования.
  • пользователю придется подождать, пока это не будет сделано, чтобы начать взаимодействие с картой, что может легко стать очень плохим пользовательским интерфейсом.

Эти две и, возможно, другие причины объясняются тем, почему Google не создавал вид масштабирования, который вы хотите использовать в картах, в первую очередь, потому что это плохая идея...

Ответ 4

@Герман Шааф Ваше решение отлично, но при двойном щелчке он пропускает несколько масштабирования : D Поэтому я сделал решение + smoothZoom Я не могу взять все кредиты, которые я редактировал код JesseDobbelaere от jsfiddle.net Это сочетание вашего и кода Джесси.

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

Я сделал несколько переменных, таких как timeOut и maxZoomIn Out... вы можете найти полный код на jsfiddle http://jsfiddle.net/dexy86/9afy9/

Ответ 5

Я пробовал перечисленные выше альтернативы, однако, всякий раз, когда я просматриваю переход в настольном браузере или мобильном приложении, все это происходит мгновенно или, по крайней мере, в течение периода времени, который незаметен для глаз из-за время между каждой итерацией цикла, по крайней мере, на аппаратном обеспечении, на котором я его тестировал.

Я использовал тот же цикл, что и другие методы, но изменил таймаут, чтобы увеличить масштаб, когда уровень масштабирования был выше, и медленнее, когда он был ниже, поэтому результаты были более заметными.

Вместо использования фиксированного периода ожидания я установил первый тайм-аут на 0, а затем последующие таймауты на следующее быстрое и грязное уравнение

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

В коде я предположил, что максимальное масштабирование равно 18, но вы можете использовать maxZoom, чтобы узнать, какой уровень масштабирования для учитывая lat/long. Мой код:

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

Ответ 6

Это будет плавно масштабироваться в желаемом месте. Попробуйте добавить эти строки:

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