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

Расширить маркер Google Maps для плавного обновления при обновлении?

Используя API Google Maps v3, я смог обновить несколько позиций маркеров с помощью вызова AJAX. Однако он не имеет никакого перехода. Код ниже:

if ( !latlong.equals( point.latlong ) ) {
    point.latlong = latlong;
    point.marker.setPosition(latlong);
}

Недостатком является то, что setPosition не имеет собственного метода анимации. Кто-нибудь знает какие-либо методы расширения setPosition, чтобы маркер мог свободно "переходить" от старого к новому? Или любые доступные методы? Я не смог найти никакой документации. Спасибо!

4b9b3361

Ответ 1

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

var map = undefined;
var marker = undefined;
var position = [43, -89];

function initialize() {

    var latlng = new google.maps.LatLng(position[0], position[1]);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    marker = new google.maps.Marker({
        position: latlng,
        map: map,
        title: "Your current location!"
    });

    google.maps.event.addListener(map, 'click', function(me) {
        var result = [me.latLng.lat(), me.latLng.lng()];
        transition(result);
    });
}

var numDeltas = 100;
var delay = 10; //milliseconds
var i = 0;
var deltaLat;
var deltaLng;
function transition(result){
    i = 0;
    deltaLat = (result[0] - position[0])/numDeltas;
    deltaLng = (result[1] - position[1])/numDeltas;
    moveMarker();
}

function moveMarker(){
    position[0] += deltaLat;
    position[1] += deltaLng;
    var latlng = new google.maps.LatLng(position[0], position[1]);
    marker.setPosition(latlng);
    if(i!=numDeltas){
        i++;
        setTimeout(moveMarker, delay);
    }
}

Это, вероятно, можно немного убрать, но это даст вам хорошее начало. Я использую метод setTimeout JavaScript для создания анимации. Первоначальный вызов 'transition' запускает анимацию. Параметр для перехода - это массив из двух элементов [lat, lng]. Функция 'transition' вычисляет размеры шагов для lat и lng на основе пары параметров анимации (numDeltas, delay). Затем он вызывает "MoveMarker". Функция moveMarker ведет простой счетчик, чтобы указать, когда маркер достиг конечного пункта назначения. Если нет, он снова вызывает себя.

Вот jsFiddle работающего кода: https://jsfiddle.net/rcravens/RFHKd/2363/

Надеюсь, это поможет.

боб

Ответ 3

Я знаю, что уже поздно, но это может помочь будущим ТАКИМ странникам.
Постановка проблемы: напишите функцию (а не библиотеку из-за конкретного варианта использования) для анимации маркера карт Google в новом месте.
Решение основано на этой удивительной библиотеке marker-animate-unobtrusive

function animateMarkerTo(marker, newPosition) {
    var options = {
        duration: 1000,
        easing: function (x, t, b, c, d) { // jquery animation: swing (easeOutQuad)
            return -c *(t/=d)*(t-2) + b;
        }
    };

    window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;

    // save current position. prefixed to avoid name collisions. separate for lat/lng to avoid calling lat()/lng() in every frame
    marker.AT_startPosition_lat = marker.getPosition().lat();
    marker.AT_startPosition_lng = marker.getPosition().lng();
    var newPosition_lat = newPosition.lat();
    var newPosition_lng = newPosition.lng();

    // crossing the 180° meridian and going the long way around the earth?
    if (Math.abs(newPosition_lng - marker.AT_startPosition_lng) > 180) {
        if (newPosition_lng > marker.AT_startPosition_lng) {
            newPosition_lng -= 360;
        } else {
            newPosition_lng += 360;
        }
    }

    var animateStep = function(marker, startTime) {
        var ellapsedTime = (new Date()).getTime() - startTime;
        var durationRatio = ellapsedTime / options.duration; // 0 - 1
        var easingDurationRatio = options.easing(durationRatio, ellapsedTime, 0, 1, options.duration);

        if (durationRatio < 1) {
            marker.setPosition({
                lat: (
                    marker.AT_startPosition_lat +
                    (newPosition_lat - marker.AT_startPosition_lat)*easingDurationRatio
                ),
                lng: (
                    marker.AT_startPosition_lng +
                    (newPosition_lng - marker.AT_startPosition_lng)*easingDurationRatio
                )
            });

            // use requestAnimationFrame if it exists on this browser. If not, use setTimeout with ~60 fps
            if (window.requestAnimationFrame) {
                marker.AT_animationHandler = window.requestAnimationFrame(function() {animateStep(marker, startTime)});
            } else {
                marker.AT_animationHandler = setTimeout(function() {animateStep(marker, startTime)}, 17);
            }

        } else {
            marker.setPosition(newPosition);
        }
    }

    // stop possibly running animation
    if (window.cancelAnimationFrame) {
        window.cancelAnimationFrame(marker.AT_animationHandler);
    } else {
        clearTimeout(marker.AT_animationHandler);
    }

    animateStep(marker, (new Date()).getTime());
}