7

Tôi có một ứng dụng bản đồ javascript đơn giản mà tôi đang làm việc trên đó yêu cầu tôi tạo hiệu ứng chuyển động của nhiều điểm đánh dấu giữa các hợp âm khác nhau. Mỗi điểm đánh dấu tự do di chuyển và tất cả các điểm đánh dấu được lưu trữ trong một danh sách mảng. Tuy nhiên, tôi đã gặp sự cố khi đưa họ đến các vị trí chuyển tiếp suôn sẻ.JS API Google Maps v3 Đánh dấu Animate giữa các tọa độ

Tôi đã thực hiện rất nhiều nghiên cứu và thử nghiệm/lỗi nhưng không may mắn, ai cũng có may mắn với điều này?

Trả lời

17

cách tiếp cận nhanh chóng-và-bẩn của tôi không liên quan đến một tấn nghiên cứu :(

Dưới đây là bản demo: http://jsfiddle.net/yV6xv/4/ Nhấn vào một điểm đánh dấu để bắt đầu di chuyển nó, sau khi nó dừng lại, bạn có thể nhấp vào một lần nữa để quay trở lại Điểm ban đầu của nó Nhấp vào trong khi đang chuyển động sẽ cho kết quả lạ.

Điểm bắt đầu và điểm cuối được xác định trước trong initialize() Hoạt ảnh được xác định bằng cách chia điểm bắt đầu và điểm cuối thành 100 phân đoạn và đặt điểm đánh dấu tại các điểm này. Vì vậy, thời gian hoạt ảnh được khắc phục: các điểm đánh dấu di chuyển các khoảng cách dài hơn "nhanh hơn" so với khoảng cách ngắn hơn.

tôi đã không làm nhiều thử nghiệm, tôi biết cách nhấp vào một dấu hiệu chuyển động sẽ cho kết quả bất ngờ (bắt đầu và điểm cuối được đặt không đúng chỗ)

Đây là "thú vị" một phần của bản 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

Cảm ơn bạn! Là một người mới làm quen với JS, điều này khá dễ hiểu (có nghĩa là: vẫn khó cho người mới bắt đầu) và giúp tôi rất nhiều. Ban đầu tôi đã chia rẽ điều này và làm cho nó trở thành một người mới bắt đầu nhưng tôi đã quay trở lại bản gốc và [được chia nhỏ lại] (http://jsfiddle.net/HYuRR/2/) để bao gồm một vòng lặp và các tốc độ khác nhau cho mỗi điểm đánh dấu. Cảm ơn một lần nữa Tina. –

8

Bạn có thể sử dụng thư viện marker-animate-unobtrusive để tạo điểm đánh dấu chuyển đổi suôn sẻ từ vị trí này sang vị trí khác.

Bạn có thể khởi điểm đánh dấu của bạn như thế:

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

Với điều này được xác định, đánh dấu của bạn suôn sẻ sẽ di chuyển đến một vị trí mới trong vòng 1 giây, chỉ cần gọi marker.setPosition().

Nếu bạn muốn tạo hiệu ứng đánh dấu qua lại, chỉ cần chuyển đổi setPosition mỗi giây.

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

P.S. Tôi là tác giả của thư viện.

+0

Làm việc tuyệt vời. Đã có thể đạt được kết quả mà không thay đổi bất kỳ mã nào. – Farveaz

+1

Đó là ý tưởng được 'không phô trương', hay khi nghe nó làm việc cho bạn. – viskin

7

Tôi không chắc chắn nếu đó là những gì bạn đang tìm kiếm nhưng tôi sẽ chia sẻ nó: Tôi đã viết mã này để mô phỏng chuyển động của ô tô với tốc độ cụ thể theo km/h. Bạn chỉ cần xác định tọa độ của mỗi điểm bạn muốn điểm đánh dấu/ô tô đi tới (sau đó nó sẽ tạo hiệu ứng đánh dấu giữa các tọa độ).

tôi sửa đổi rcravens's answer để có được điều này:

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

Lưu ý rằng bạn cần phải thêm "hình học" thư viện khi bạn bao gồm bản đồ google để có thể sử dụng google.maps.geometry.spherical.computeDistanceBetween : http://maps.google.com/maps/api/js?sensor=true&libraries=geometry

Hy vọng điều đó sẽ hữu ích!

0

Cách khác là sử dụng chuyển tiếp CSS.Bit quan trọng là xác định các DIV mà Google Maps đang sử dụng cho điểm đánh dấu của bạn (Có 2 sự minh bạch cho các sự kiện liên lạc) Cuộc điều tra đã được thực hiện cho bạn và bạn thực sự chỉ phải hiểu nó một lần.

Ví dụ hoàn chỉnh có thể được tìm thấy here Xem mức độ trôi chảy của Hansel và Gretel trên bản đồ! Và thời gian chuyển tiếp kết hợp nếu có bất kỳ sự chậm trễ nào.

Tất cả các mã cho Brotkrumen Cuối cùng Web App của tôi có thể được tìm thấy here bạn sẽ chủ yếu quan tâm đến các tập tin HandleMap.js nhưng có một aaa_readme.txt

Đây là một phần của mã: -

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