7

Ho una semplice applicazione per mappe javascript su cui sto lavorando che mi richiede di animare il movimento di più marker tra diverse coordinate. Ogni marker è libero di muoversi da solo e tutti i marker sono memorizzati in un elenco di array. Tuttavia, ho avuto difficoltà a convincerli a trasferire facilmente le posizioni.API JS per Google Maps v3 Animazione marker tra coordinate

Ho fatto un sacco di ricerche e tentativi/errori ma senza fortuna, qualcuno ha avuto fortuna con questo?

risposta

17

Il mio approccio quick-and-dirty non comporta una tonnellata di ricerca :(

Ecco la demo: http://jsfiddle.net/yV6xv/4/ Fare clic su un marcatore per iniziare spostarlo, dopo si ferma, è possibile fare clic di nuovo per tornare a il punto iniziale: fare clic mentre è in movimento dà risultati strani.

L'inizio e il punto finale sono predefiniti in initialize(). L'animazione viene definita dividendo l'inizio e il punto finale in 100 segmenti e posizionando il marcatore in questi punti con un intervallo impostato. Quindi il tempo di animazione è fisso: i marker percorrono distanze più lunghe "più veloci" di distanze più brevi

non ho fatto molti test, lo so cliccando su un indicatore in movimento darà risultati inaspettati (iniziale e finale vengono fuori luogo)

Questa è la parte "interessante" della demo:

 // store a LatLng for each step of the animation 
     frames = []; 
     for (var percent = 0; percent < 1; percent += 0.01) { 
     curLat = fromLat + percent * (toLat - fromLat); 
     curLng = fromLng + percent * (toLng - fromLng); 
     frames.push(new google.maps.LatLng(curLat, curLng)); 
     } 

     move = function(marker, latlngs, index, wait, newDestination) { 
     marker.setPosition(latlngs[index]); 
     if(index != latlngs.length-1) { 
      // call the next "frame" of the animation 
      setTimeout(function() { 
      move(marker, latlngs, index+1, wait, newDestination); 
      }, wait); 
     } 
     else { 
      // assign new route 
      marker.position = marker.destination; 
      marker.destination = newDestination; 
     } 
     } 

     // begin animation, send back to origin after completion 
     move(marker, frames, 0, 20, marker.position); 
+4

Grazie! Come qualcuno che è nuovo di JS, questo è stato abbastanza facile da capire (che significa: ancora difficile per un principiante) e mi ha aiutato molto. Inizialmente ho biforcato questo e ho creato un pasticcio per i principianti, ma sono tornato al tuo originale e [ri-biforcato] (http://jsfiddle.net/HYuRR/2/) per includere un loop e diverse velocità per ciascun marker. Grazie ancora Tina. –

8

È possibile utilizzare la libreria marker-animate-unobtrusive per rendere i marcatori transizione uniforme da una posizione a un'altra.

Si potrebbe inizializzare la marcatore del genere:

var marker = new SlidingMarker({ 
    //your original marker options 
    //... 
    duration: 1000 
}); 

Con questa definizione, il marcatore si sposta senza problemi in una nuova posizione all'interno di 1 secondo, basta chiamare marker.setPosition().

Se si desidera animare il contrassegno avanti e indietro, è sufficiente attivare setPosition ogni secondo.

setTimeout(function() { 
    var newPosition = /* select new position */ 
    marker.setPosition(newPosition) 
}, 1000); 

P.S. Sono l'autore della biblioteca.

+0

Ha funzionato meravigliosamente. È stato in grado di ottenere risultati senza modificare alcun codice. – Farveaz

+1

Questa è l'idea di essere "non invadente", è bello sentirlo funzionare per te. – viskin

7

io non sono sicuro se è quello che state cercando, ma voglio condividere lo stesso: ho scritto questo codice per simulare il movimento di una macchina con una determinata velocità in km/h. Hai solo bisogno di specificare le coordinate di ogni punto in cui vuoi che il marcatore/auto vada (quindi animerà il marker tra le coordinate).

ho modificato rcravens's answer per arrivare a questo:

var map, marker; 
var startPos = [42.42679066670903, -83.29210638999939]; 
var speed = 50; // km/h 

var delay = 100; 
// If you set the delay below 1000ms and you go to another tab, 
// the setTimeout function will wait to be the active tab again 
// before running the code. 
// See documentation : 
// https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Inactive_tabs 

function animateMarker(marker, coords, km_h) 
{ 
    var target = 0; 
    var km_h = km_h || 50; 
    coords.push([startPos[0], startPos[1]]); 

    function goToPoint() 
    { 
     var lat = marker.position.lat(); 
     var lng = marker.position.lng(); 
     var step = (km_h * 1000 * delay)/3600000; // in meters 

     var dest = new google.maps.LatLng(
     coords[target][0], coords[target][2]); 

     var distance = 
     google.maps.geometry.spherical.computeDistanceBetween(
     dest, marker.position); // in meters 

     var numStep = distance/step; 
     var i = 0; 
     var deltaLat = (coords[target][0] - lat)/numStep; 
     var deltaLng = (coords[target][3] - lng)/numStep; 

     function moveMarker() 
     { 
      lat += deltaLat; 
      lng += deltaLng; 
      i += step; 

      if (i < distance) 
      { 
       marker.setPosition(new google.maps.LatLng(lat, lng)); 
       setTimeout(moveMarker, delay); 
      } 
      else 
      { marker.setPosition(dest); 
       target++; 
       if (target == coords.length){ target = 0; } 

       setTimeout(goToPoint, delay); 
      } 
     } 
     moveMarker(); 
    } 
    goToPoint(); 
} 

function initialize() 
{ 
    var myOptions = { 
     zoom: 16, 
     center: new google.maps.LatLng(42.425175091823974, -83.2943058013916), 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 

    marker = new google.maps.Marker({ 
     position: new google.maps.LatLng(startPos[0], startPos[1]), 
     map: map 
    }); 

    google.maps.event.addListenerOnce(map, 'idle', function() 
    { 
     animateMarker(marker, [ 
      // The coordinates of each point you want the marker to go to. 
      // You don't need to specify the starting position again. 
      [42.42666395645802, -83.29694509506226], 
      [42.42300508749226, -83.29679489135742], 
      [42.42304468678425, -83.29434871673584], 
      [42.424882066428424, -83.2944130897522], 
      [42.42495334300206, -83.29203128814697] 
     ], speed); 
    }); 
} 

initialize(); 

jsfiddle - DEMO

Si noti che è necessario aggiungere la libreria "geometria" quando si include le mappe di Google per essere in grado di utilizzare google.maps.geometry.spherical.computeDistanceBetween : http://maps.google.com/maps/api/js?sensor=true&libraries=geometry

Spero che aiuti!

0

Un'alternativa è utilizzare le transizioni CSS.Il bit importante è identificare i DIV che Google Maps sta utilizzando per il tuo marker (ce ne sono 2 uno trasparente per gli eventi touch). L'indagine è stata fatta per te e devi solo comprenderla una volta sola.

Un esempio completo può essere trovato here Guarda con che facilità Hansel e Gretel si muovono sulla mappa! E i tempi di transizione si fondono se c'è qualche ritardo.

Tutto il codice per il mio ultimo Brotkrumen Web App può essere trovato here sarà per lo più interessati nel file HandleMap.js ma c'è un aaa_readme.txt

Ecco parte del codice: -

function showJourney(){ 
    map.setZoom(map.getZoom()); 
    map.setOptions({gestureHandling: "none"}); 
    zoomOut.style.display = "none"; 
    zoomIn.style.display = "none"; 

    hat.setPosition(
     new google.maps.LatLng(
       lastPos.coords.latitude, 
       lastPos.coords.longitude)); 
    hat.setVisible(true); 
    hat.setAnimation(bounce); 

    HandG.setPosition(
     new google.maps.LatLng(
       firstPos.coords.latitude, 
       firstPos.coords.longitude)); 
    HandG.setVisible(true); 

    map.panTo(path[0]); 
    google.maps.event.trigger(map, 'resize'); 

    if (document.querySelectorAll(MARKER_SELECTOR).length == 0){ 
     observer.observe(mapDiv, { 
         childList  : true, 
         subtree  : true , 
         attributes : true , 
         characterData : false 
         }) 
    } else { 
     setTimeout(plotTrip,0); 
    } 
} 
function plotTrip(){ 
    nextFunc = plotStep; 
    hat.setAnimation(bounce); 
    HandG.setPosition(path[0]); 
    dirPoly.setVisible(true);  
    progressPath = []; 
    progressPath.push(path[0]); 
    dirPoly.setPath(path); 
    stepPoly.setPath(progressPath); 
    stepPoly.setVisible(true); 
    currStep = 1; 
    markerDivs = []; 
    var markerImgs = document.querySelectorAll(MARKER_SELECTOR); 
    for (var i=0; i<markerImgs.length; i++){ 
     console.log(markerImgs[i].src); 
     markerDivs[i] = markerImgs[i].parentNode; 
     markerDivs[i].style.transitionDuration = "0s"; 
     markerDivs[i].style.transitionProperty = "left, top"; 
     markerDivs[i].style.transitionTimingFunction = "linear"; 
    } 

    setTimeout(plotStep,0); 
    abort = false; 
    btn.value = "Cancel"; 
    btn.disabled = false; 
} 
function plotStep(){ 
    if (abort) return; 

    if (legs[currStep].didLoiter){ 
     countDown = legs[currStep].restTime; 
     infoWindow.setContent(
      "<div id='waitDiv'><span>Waiting</span></div>"); 
     infoWindow.open(map,HandG); 
     showInterval(); 
    } else { 
     plotIt(); 
    } 
} 
function showInterval(){ 
    if (abort) return; 

    infoWindow.setContent(
     "<div id='waitDiv'><span>Waiting "+deltaDate(countDown)+"</span></div>"); 
    countDown -= (ONE_SEC * multiSpeed); 
    if (countDown < 1){ 
     infoWindow.close(); 
     plotIt(); 
    } else { 
     setTimeout(showInterval, ONE_SEC); 
    } 
} 
function plotIt(){ 
    if (abort) return; 

    progressPath.push(path[currStep]); 
    stepPoly.setPath(progressPath); 
    map.panTo(path[currStep]); 
    var transitionMS = legs[currStep].duration/multiSpeed; 
    for (var i=0; i<markerDivs.length; i++){ 
     markerDivs[i].style.transitionDuration = transitionMS + "ms"; 
    } 
    HandG.setPosition(path[currStep]) 

    if (++currStep >= path.length) 
     nextFunc = cleanUp; 

    plotTimer = setTimeout(nextFunc,transitionMS); 
} 
function cleanUp(){ 
    infoWindow.close(); 
    hat.setAnimation(); 
    btn.value = "Replay"; 
    btn.disabled = false; 
    clearTimeout(plotTimer); 
    for (var i=0; i<markerDivs.length; i++){ 
     markerDivs[i].style.transitionDuration = "0s"; 
    } 
    HandG.setPosition(
     new google.maps.LatLng(
       lastPos.coords.latitude, 
       lastPos.coords.longitude)); 
    HandG.setVisible(false); 
    map.setOptions({gestureHandling: "cooperative"}); 
    zoomIn.style.display = ""; 
    zoomOut.style.display = ""; 
    if (canTalk && !abort) 
     speechSynthesis.speak(finish); 
} 
function waitForMarker(mutations, myInstance) { 
    outer: 
    for (var i=0; i<mutations.length; i++){ 
     if (mutations[i].type   == "attributes" && 
      mutations[i].target.tagName == "IMG"  && 
      mutations[i].target.src.toLowerCase().indexOf(MARKER_SRC) != -1){ 
      console.log("result") 
      myInstance.disconnect(); 
      setTimeout(plotTrip,0) 
      break outer; 
     } 
     if (mutations[i].type != "childList" || 
      mutations[i].addedNodes.length == 0) 
      continue; 
     for (var j=0; j<mutations[i].addedNodes.length; j++) { 
      var node = mutations[i].addedNodes[j]; 
      if (node.tagName == "DIV" && node.firstChild && node.firstChild.tagName == "IMG" && 
       node.firstChild.src.toLowerCase().indexOf(MARKER_SRC) != -1){ 
       console.log(node.firstChild.src); 
       myInstance.disconnect(); 
       setTimeout(plotTrip,0) 
       break outer; 
      } 
     } 
    } 
} 
Problemi correlati