7

我有一个简单的javascript地图应用程序,我正在研究这需要我动画不同坐标之间的多个标记的运动。每个标记都可以自​​由移动,并且所有标记都存储在数组列表中。但是,我一直无法让他们顺利过渡地点。JS谷歌地图API v3动画坐标之间的标记

我已经做了大量的研究和试验/错误,但没有运气,任何人都有这样的运气?

回答

17

我的快速和肮脏的方法不涉及一吨的研究:(

这里的演示:http://jsfiddle.net/yV6xv/4/点击一个标记,以开始移动它,它停止后,您可以再次点击返回它的初始点。点击在运动的同时给出奇怪的结果。

起点和终点被预定义在initialize()。动画是通过将起点和终点为100米的段,并与一组间隔放置的标记在这些点定义的。所以动画时间是固定的:标记比较短的距离“更快”地传播更长的距离。

我没有做太多的测试,我知道在点击一个移动标记将给予意想不到的结果(起点和终点得到错位的)

这是演示的“有趣”的部分:

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

谢谢!作为JS的新手,这很容易理解(这意味着:初学者仍然很难),并且帮助了我很多。我原本分叉这使它成为一个初学者混乱,但我回到你的原始和[重叉](http://jsfiddle.net/HYuRR/2/)它包括一个循环和不同的速度为每个标记。再次感谢蒂娜。 –

8

您可以使用marker-animate-unobtrusive库使标记 从一个位置平滑过渡到另一个位置。

你可以初始化标记像:

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

有了这个定义,您的标记将顺利地移动到新的位置在1秒钟内,只需调用marker.setPosition()。

如果您想要前后移动标记,只需每秒切换setPosition。

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

P.S.我是图书馆的作者。

+0

工作出色。能够在不更改任何代码的情况下实现结果。 – Farveaz

+1

这就是'不显眼'的想法,很高兴听到它为你工作。 – viskin

7

我不确定它是不是你正在寻找的东西,但我会分享它:我写这个代码到模拟汽车以特定的速度公里/小时的运动。您只需指定您希望标记/汽车前往的每个点的坐标(然后它将在坐标之间对标记进行动画处理)。

我修改rcravens's answer得到这样的:

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

请注意,您需要在包括谷歌地图,能够使用google.maps.geometry.spherical.computeDistanceBetween添加“几何”库: http://maps.google.com/maps/api/js?sensor=true&libraries=geometry

希望它有帮助!

0

另一种方法是使用CSS转换。重要的是识别谷歌地图用于标记的DIV(有2个对于触摸事件是透明的)调查已经完成了,你只需要了解它一次。

可以找到一个完整的示例here看看Hansel和Gretel在地图上的移动过程如何顺利!如果有任何延迟,转换时间会合并。

所有我Brotkrumen终极Web应用程序的代码可以发现here你会在HandleMap.js文件最感兴趣,但有一个aaa_readme.txt

下面是部分代码: -

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