Javascript JS Google Maps API v3 坐标之间的动画标记

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10904476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:31:02  来源:igfitidea点击:

JS Google Maps API v3 Animate Marker Between Coordinates

javascriptgoogle-mapsanimationgoogle-maps-api-3google-maps-markers

提问by John Snow

I have a simple javascript maps application that I'm working on that requires me to animate the movement of multiple markers between different coords. Each marker is free to move on its own and all markers are stored in an array list. However, I have been having trouble getting them to smoothly transition locations.

我有一个简单的 javascript 地图应用程序,我正在处理它需要我为不同坐标之间的多个标记的移动设置动画。每个标记都可以自​​行移动,所有标记都存储在一个数组列表中。但是,我一直无法让他们顺利过渡到地点。

I've done a ton of research and trial/error but no luck, anyone have any luck with this?

我已经做了大量的研究和试验/错误,但没有运气,有人有这方面的运气吗?

回答by Tina CG Hoehr

My quick-and-dirty approach does not involve a ton of research :(

我的快速而肮脏的方法不涉及大量研究:(

Here's the demo: http://jsfiddle.net/yV6xv/4/Click on a marker to begin moving it, after it stops, you can click again to go back to its initial point. Clicking while in motion gives strange results.

这是演示:http: //jsfiddle.net/yV6xv/4/点击一个标记开始移动它,它停止后,你可以再次点击回到它的初始点。在运动中单击会产生奇怪的结果。

Start and endpoints are predefined in initialize(). The animation is defined by dividing the start and endpoints into 100 segments, and placing the marker at these points with a set interval. So the animation time is fixed: markers travel longer distances "faster" than shorter distances.

起点和终点在initialize(). 动画的定义是将起点和终点分成 100 段,并以设定的间隔将标记放置在这些点上。所以动画时间是固定的:标记比较短的距离“更快”地移动更长的距离。

I didn't do much testing, I know clicking on a moving marker will give unexpected results (start and endpoints get misplaced)

我没有做太多测试,我知道点击移动标记会产生意想不到的结果(起点和终点错位)

This is the "interesting" part of the 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);

回答by viskin

You can use marker-animate-unobtrusivelibrary to make markers smoothly transition from one location to another.

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

You could initialize your marker like that:

你可以像这样初始化你的标记:

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

With this defined, your marker will smoothly move to a new position within 1 second, just call marker.setPosition().

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

If you want to animate marker back-and-forth, just toggle setPosition each second.

如果您想来回为标记设置动画,只需每秒切换一次 setPosition。

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

P.S. I'm the author of the library.

PS我是图书馆的作者。

回答by pmrotule

I'm not sure if it is what you are looking for but I will share it anyway : I wrote this code to simulate the movement of a carwith a specific speed in km/h. You just need to specify the coordinates of each point you want the marker/car to go to (then it will animate the marker between the coordinates).

我不确定这是否是您要找的东西,但无论如何我都会分享它:我编写了这段代码来模拟以公里/小时为单位的特定速度的汽车的运动。您只需要指定您希望标记/汽车去的每个点的坐标(然后它将在坐标之间为标记设置动画)。

I modified rcravens's answerto get to this:

我修改了rcravens 的答案来解决这个问题:

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

jsfiddle -演示

Note that you need to add the "geometry" library when you include google maps to be able to use google.maps.geometry.spherical.computeDistanceBetween: http://maps.google.com/maps/api/js?sensor=true&libraries=geometry

请注意,当您包含谷歌地图时,您需要添加“几何”库才能使用google.maps.geometry.spherical.computeDistanceBetweenhttp: //maps.google.com/maps/api/js?sensor=true&libraries=geometry

Hope it helps!

希望能帮助到你!

回答by McMurphy

An alternative is to use CSS transitions. The important bit is identifying the DIVs Google Maps is using for your marker (There are 2 one is transparent for touch events) The investigation has been done for you and you really only have to understand it once.

另一种方法是使用 CSS 过渡。重要的一点是识别 Google Maps 用于标记的 DIV(有 2 个对于触摸事件是透明的)调查已经为您完成,您实际上只需要了解一次。

A complete example can be found hereSee how smoothly Hansel and Gretel move around the map! And the transition times coalesce if there is any delay.

一个完整的例子可以在这里找到看看 Hansel 和 Gretel 在地图上的移动有多顺畅!如果有任何延迟,转换时间会合并。

All the code for my Brotkrumen Ultimate Web App can be found hereyou will be mostly interested in the HandleMap.js file but there is a aaa_readme.txt

我的 Brotkrumen Ultimate Web App 的所有代码都可以在这里找到你最感兴趣的 HandleMap.js 文件,但有一个 aaa_readme.txt

Here is part of the code: -

这是代码的一部分:-

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