【问题标题】:Show a moving marker on the map在地图上显示移动标记
【发布时间】:2013-04-26 16:02:35
【问题描述】:

当车辆在道路上移动时,我正在尝试在地图上移动标记(不会消失并再次出现)。

我有两个 latLng 值,我想在这两个值之间移动标记,直到车辆发送下一个点。然后再次重复该过程。

我尝试了什么:[这不是一个非常有效的方法,我知道]

我的想法是使用以下技术来实现上述内容:

1) 在两者之间画一条线。

2) 获取折线 1/10 部分上每个点的 latLng。

3) 沿着折线在地图上标记 10 个点。

这是我的代码:

var isOpen = false;
var deviceID;
var accountID;
var displayNameOfVehicle;
var maps = {};
var lt_markers = {};
var lt_polyLine = {};
function drawMap(jsonData, mapObj, device, deleteMarker) {
    var oldposition = null;
    var oldimage = null;
    var arrayOflatLng = [];

    var lat = jsonData[0].latitude;
    var lng = jsonData[0].longitude;
    //alert(jsonData[0].imagePath);

    var myLatLng = new google.maps.LatLng(lat, lng);

    if (deleteMarker == true) {
        if (lt_markers["marker" + device] != null) {
            oldimage = lt_markers["marker" + device].getIcon().url;
            oldposition = lt_markers["marker" + device].getPosition();
            lt_markers["marker" + device].setMap(null);
            lt_markers["marker" + device] = null;
        }
        else {
            console.log('marker is null');
            oldimage = new google.maps.MarkerImage(jsonData[0].imagePath,
                                                     null,
                                                     null,
                                                      new google.maps.Point(5, 17), //(15,27),
                                                     new google.maps.Size(30, 30));
            oldposition = myLatLng;
        }
    }


    var image = new google.maps.MarkerImage(jsonData[0].imagePath,
                                                     null,
                                                     null,
                                                      new google.maps.Point(5, 17), //(15,27),
                                                     new google.maps.Size(30, 30));
    lt_markers["marker" + device] = new google.maps.Marker({
        position: myLatLng,
        icon: image,
        title: jsonData[0].address
    });
    if (oldposition == myLatLng) {
        alert('it is same');
        lt_markers["marker" + device].setMap(mapObj);
        mapObj.panTo(myLatLng);
    }
    else {
        alert('it is not same');
        var markMarker = null;
        var i = 10;
        for (i = 10; i <= 100; i + 10) {
            //-------
            //  setTimeout(function() {
            if (markMarker != null) {
                markMarker.setMap(null);
                markMarker = null;
            }
            alert('inside the loop');
            var intermediatelatlng = mercatorInterpolate(mapObj, oldposition, myLatLng, i / 100);
            alert('Intermediate Latlng is :' + intermediatelatlng);
            arrayOflatLng.push(intermediatelatlng);

            var flightPath = new google.maps.Polyline({
                path: arrayOflatLng,
                strokeColor: "#FFFFFF",
                strokeOpacity: 1.0,
                strokeWeight: 1
            });
            flightPath.setMap(mapObj);
            if (i != 100) {
                markMarker = new google.maps.Marker({
                    position: intermediatelatlng,
                    icon: image,
                    title: jsonData[0].address,
                    map: mapObj
                });

            }
            else {
                markMarker = new google.maps.Marker({
                    position: intermediatelatlng,
                    icon: oldimage,
                    title: jsonData[0].address,
                    map: mapObj
                });                
            }
            mapObj.panTo(intermediatelatlng);
            //--------
            //   }, 1000);
        }
    }

}
function mercatorInterpolate(map, latLngFrom, latLngTo, fraction) {
    // Get projected points
    var projection = map.getProjection();
    var pointFrom = projection.fromLatLngToPoint(latLngFrom);
    var pointTo = projection.fromLatLngToPoint(latLngTo);
    // Adjust for lines that cross the 180 meridian
    if (Math.abs(pointTo.x - pointFrom.x) > 128) {
        if (pointTo.x > pointFrom.x)
            pointTo.x -= 256;
        else
            pointTo.x += 256;
    }
    // Calculate point between
    var x = pointFrom.x + (pointTo.x - pointFrom.x) * fraction;
    var y = pointFrom.y + (pointTo.y - pointFrom.y) * fraction;
    var pointBetween = new google.maps.Point(x, y);
    // Project back to lat/lng
    var latLngBetween = projection.fromPointToLatLng(pointBetween);
    return latLngBetween;
}

面临的问题:

1) 标记未显示在地图上,因为绘制和删除标记的过程非常快,以至于标记在屏幕上不可见。我试过 setTimeOut,但它根本没有帮助。

2) 如果我让浏览器运行这段代码超过 5 分钟,浏览器就会崩溃。

注意:使用 setInterval 每 10 秒调用一次上述函数。

有什么更好的解决方案?请帮忙..

【问题讨论】:

  • 使用回调函数在你插值的每个点上都画一个标记有什么问题?所以你画一个标记;在下一个周期中,您将其删除;并在下一个计算的 latlng 上放置一个标记...
  • 感谢 GeocodeZip..!让我试一次。!
  • Thomas 你能解释一下代码中的 callabck 机制吗?
  • 你创建了一个回调函数(寻找 requestAnimationFrame 和 setTimeout 函数)。该函数将每 x ms 调用一次。这就是动画的帧速率。在回调函数中添加一个新标记并删除旧标记。

标签: javascript jquery google-maps google-maps-api-3 cross-browser


【解决方案1】:

为了让marker移动得比较顺畅,你需要

  • 多段线的每 1/10 部分更新一次以上(至少每隔几个像素)
  • 更频繁地调用更新方法
  • 不要删除并重新添加标记

例如:

var counter = 0;
interval = window.setInterval(function() { 
  counter++;
  // just pretend you were doing a real calculation of
  // new position along the complex path
  var pos = new google.maps.LatLng(35, -110 + counter / 100);
  marker.setPosition(pos);
  if (counter >= 1000) {
    window.clearInterval(interval);   
  }
}, 10);

我在http://jsfiddle.net/bmSbU/2/ 做了一个简单的例子,它显示了一个标记沿着直线移动。如果这是您想要的,上面的大部分代码都可以重复使用(或查看http://broady.github.io/maps-examples/points-along-line/along-directions.html

【讨论】:

  • 感谢您提供如此出色的答案..用小提琴证明您已经完成了它,它也适用于其他人..!非常感谢。!!
  • @writeToBhuwan:您能否分享更新后的小提琴链接,因为两个链接都已损坏?
  • 请重新上传死链接。
【解决方案2】:

您可以使用marker-animate-unobtrusive 库来制作标记 从一个位置平滑过渡到另一个位置(而不是重新出现)。

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

var marker = new SlidingMarker({
   //your original marker options
});

每次新车坐标到达时调用marker.setPosition()。

附:我是图书馆的作者。

【讨论】:

  • 谢谢!这是一个惊人的答案。 !图书馆也做得很好。
  • 知道如何播放/暂停动画吗?
  • 您可以将动画的持续时间设置为 0。从技术上讲,这将禁用动画。
  • 如果你想让你的车在动画中间停下来,你可以调用marker.setPosition(marker.getAnimationPosition())。这会将动画目标设置为当前可见位置,并停止它。
  • @viskin 是一个很好的库。你用什么来动画标记?您是使用 setPosition() 方法设置标记的位置还是为动画移除/创建新标记?
【解决方案3】:

为什么不保留现有的 Marker/ MarkerImage 并调用 setPosition() 来移动它,无论是在计时器上还是随着位置的变化?

删除它并重新创建它是导致它闪烁/闪烁并最终崩溃的原因。如果您保留相同的实例但只是移动它,您应该会做得更好。

参见:Marker.setPosition()

https://developers.google.com/maps/documentation/javascript/reference#Marker

【讨论】:

    猜你喜欢
    • 2020-07-02
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多