【问题标题】:Hundreds of markers moving simultaneously. Bad performance数百个标记同时移动。表现不佳
【发布时间】:2015-03-23 14:16:49
【问题描述】:

我正在使用 google maps api v3,我需要同时移动许多(数百个)标记。从服务器,我得到对象数组,代表一个标记,它的坐标随着时间的推移(几个月)移动,按移动时间排序。在我的地图上方,我有一个进度条,用“月:年”文本表示时间。我的代码所做的是在准确的时间移动标记(并绘制折线),使其适合当前显示在“时间进度条”上的时间。在标记停止的每个位置,我都会留下一个新标记来显示运动的历史。整个过程一遍又一遍地重复(setInterval() 函数)。我的代码正在运行,问题是性能,所以我问:有什么办法可以提高性能吗?比我做得更好的方法吗?一定有什么。这是我的代码:

if (mapOverTime != null) {
    trackables.forEach(function (trackable) {
        var marker = new google.maps.Marker({
            map: mapOverTime,
            draggable: false,
            clickable: false,
            icon: geoIcon,
            animation: google.maps.Animation.none,                                
            zIndex: 2
        });            

        var polyline = new google.maps.Polyline(polyOptions);
        polyline.setMap(mapOverTime);
        // adding these to arrays so i can access and remove them from the map later
        markersArray.push(marker);
        polylineArray.push(polyline);
        trackable.years.forEach(function(year) {
            $.each(year.months, function(index, month) {
                setTimeout(function() {
                    if (month.coordinates.length > 0) {
                        var moveCounter = month.coordinates.length;
                        var timeToMove = Math.floor(pause_interval / moveCounter);
                        $.each(month.coordinates, function(i, position) {
                            var latTo = position.latitude;
                            var lngTo = position.longitude;
                            var destination = new google.maps.LatLng(latTo, lngTo);
                            setTimeout(function() {
                                moveToPosition(marker, destination, polyline);
                            }, (i) * timeToMove);
                        });
                    }
                }, pause_interval * index);
            });
        });
    });
}

这是使动作发生的函数:

function moveToPosition(marker, destination, polyline) {
  // current path of the polyline
  var path = polyline.getPath();
  // add new coordinate
  path.push(destination);
  // rendering whole line would make the map even more chaotic, this makes the line dissapear after 8 moves of the marker
  if (path.getLength() > 8) // comment out to render whole 
      th.removeAt(0); // path of polyline
  // set marker position to the new one
  marker.setPosition(destination);
  // render new marker on this position so that it is well visible where the coins were
  var historyPoint = new google.maps.Marker({
    map: mapOverTime,
    draggable: false,
    icon: historyIcon,
    animation: google.maps.Animation.none,
    zIndex: 0
  });
  historyPoint.setPosition(destination);
  // again add to global array so i can set access and remove this marker from the map later
  historyPoints.push(historyPoint);        
}

我唯一要做的就是遍历所有标记及其坐标,在给定时间移动标记,在其后面画线,在新位置创建新标记,然后寻找另一个坐标。当 1 次迭代结束时,所有对象都从地图中移除并重新开始该过程。知道如何提高性能吗?或者唯一的解决方案是减少我要渲染的标记数量?感谢您的意见!

【问题讨论】:

  • 只是为了好玩,您能否在创建新标记时增加一个计数器,并让该页面运行一分钟,然后看看有多少标记? (或者也许只是看看historyPoints.length
  • 我总共得到大约 26 000 个坐标,分布在大约 250 个标记之间。这意味着每个标记平均有 104 个“历史点”。时间跨度为 7 个月 = 每个标记每月 15 次移动。渲染一个月的所有动作大约需要 10 秒 :)
  • 所以,标记的数量远远超过“数百个”,更像是“一万个”......这不可能快速运行。
  • 您可能希望将您的代码发布到codereview.stackexchange.com
  • th.removeAt(0); // path of polyline - 应该是path,而不是th,对吧?

标签: javascript google-maps google-maps-api-3


【解决方案1】:

建议:

  • 为什么要指定animation: google.maps.Animation.none,?如果您不使用它,只需将其删除。而根据docs,有两个值,BOUNCEDROP,所以无论如何都没有none值。

  • 如果可以的话,使用标准的javascript数组循环,而不是jquery的$.each()it's faster

  • 您创建两个变量只是为了指定目的地坐标。您使用它们一次,再也不会使用它们,那么为什么不直接使用原始值呢?即

    var latTo = position.latitude;
    var lngTo = position.longitude;
    var destination = new google.maps.LatLng(latTo, lngTo);
    

变成了

    var destination = new google.maps.LatLng(position.latitude, position.longitude);
  • 您可以在此处进行的另一项改进。使用简写的内联结构符号来指定目标坐标。它应该减少创建数百个 LatLng 对象的一些开销。即

    var destination = new google.maps.LatLng(position.latitude, position.longitude);
    

然后变成:

    var destination = {lat: position.latitude, lng: position.longitude};
  • 创建折线,然后设置地图:

    var polyline = new google.maps.Polyline(polyOptions);
    polyline.setMap(mapOverTime);
    

我一直看到这个,但一直不明白...只需将 map: mapOverTime 添加到 polyOptions,就不必再进行额外的函数调用了。

  • 与historyPoint类似...不要在上面调用setPosition(),只需在创建标记时传递的选项中指定position: destination

所有这些都是小事,可能与尝试一次移动数百个标记几乎没有什么不同,但我仍然建议您尝试一下。

【讨论】:

  • 感谢您的建议,我很感激,它肯定会有所帮助。尽管如此,我还是在想,如果没有我可以选择的不同方法,从根本上提高性能:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
  • 2019-05-04
  • 2020-07-02
  • 2011-02-07
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
相关资源
最近更新 更多