【问题标题】:Google Maps API v3 - Multiple points with animationGoogle Maps API v3 - 多点动画
【发布时间】:2012-07-04 06:49:31
【问题描述】:

我正在构建一个成员目录,该目录以及按名称和与城镇或城市的距离的顺序列出成员,将使用 Google Maps API v3 在地图上显示。

我已经让它几乎按照我想要的方式工作了,但我担心它有点慢。我已经在异步加载它,但是标记存在问题。

我希望加载地图,然后标记快速连续地一个接一个地出现在放置动画中。目前有一个延迟,它们都一起下降,有时它们出现在地图上然后下降,这看起来很奇怪。

我正在使用 PHP foreach 脚本(来自 MYSQL 数据库)为成员输出 javascript 数组 - 地图上可以有 10 到 400 个标记之间的任何位置,但通常一次不超过 100 个。

为简洁起见,我在下面的示例中只包含了 4 个标记(正如我之前所说,它是从 PHP foreach 脚本输出的):

<script>
var infowindow = null;
$(document).ready(function () { initialize();  });
function initialize() {
    var centerMap = new google.maps.LatLng(53.1,-2.2);
    var myOptions = {
        zoom: 9,
        center: centerMap,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false
    }

    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    setMarkers(map, sites);
    infowindow = new google.maps.InfoWindow({
            content: "loading..."
        });
}

 var sites = [
 ['Joe Bloggs',52.1022,-2.1070,1,"Member &nbsp;<a href=\"#\">Joe Bloggs</a>"],                              
 ['Peter Pan',52.2022,-2.2070,1,"Member &nbsp;<a href=\"#\">Peter Pan</a>"],                                
 ['Andrew Andrewson',52.0322,-2.0170,1,"Member &nbsp;<a href=\"#\">Andrew Andrewson</a>"],                              
 ['Peter Peterson',52.0022,-2.0070,1,"Member &nbsp;<a href=\"#\">Peter Peterson</a>"],  
 ];

function setMarkers(map, markers) {
    for (var i = 0; i < markers.length; i++) {
        var sites = markers[i];
        var siteLatLng = new google.maps.LatLng(sites[1], sites[2]);
        var marker = new google.maps.Marker({
            position: siteLatLng,
            map: map,
            title: sites[0],
            zIndex: sites[3],
            html: sites[4],
            animation: google.maps.Animation.DROP
        });

        var contentString = "Some content";
        google.maps.event.addListener(marker, "click", function () {
            infowindow.setContent(this.html);
            infowindow.open(map, this);
        });
    }
}


  function loadScript() {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?key=my-key-is-here&sensor=false&' +'callback=initialize';
    document.body.appendChild(script);
  }

  window.onload = loadScript;
</script>

如何加快速度并让标记在页面加载后出现在拖放动画中?

【问题讨论】:

  • 没有延迟绘制后续标记的代码。使用 setTimeout 函数添加适当的延迟。

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


【解决方案1】:

如果您的页面加载时间很长,您可以选择使用 callback 异步加载 Google Maps API,该callback 可以定义为加载 Google Maps JavaScript 库的 URL 上的参数:

<script>
window.onload = loadGoogleMaps;

function loadGoogleMaps() {
   var script = document.createElement("script");
   script.type = "text/javascript";
   script.src =    
     "http://maps.googleapis.com/maps/api/jssensor=false&callback=initialize";
   document.body.appendChild(script);
}

这将允许您保留现有的 initialize 函数,该函数将在 Google Maps JavaScript 库完全加载后运行,但您需要删除当前在您的 $(document).ready 中的对 initialize() 的调用,所以它不会运行两次。

您不应该看到标记放置在地图上的两步过程,然后是 DROP 动画。您可能还想查看 setMarkers 函数的运行时间,因为如果运行时间过长,则可能是您所描述的根本原因。

根据后续评论编辑:

如果您想创建所有标记,可以在 JavaScript 中使用,但在每个标记创建之间添加延迟是 JavaScript setTimeout( function, delayInMilliseconds 函数。您必须在调用期间跟踪您在标记数组中的位置,但它可以将工作划分为不同的工作单元。使用setTimeout,您应该能够在每个标记放置之间添加一个短暂的延迟,这应该会给您想要达到的效果。

【讨论】:

  • 我已经在我的脚本中使用了回调(至少我认为我是——它在我上面列出的脚本中看起来是一样的)。该页面加载速度很快,只是谷歌地图需要一段时间才能加载。也许这对于 100 多个标记是可以预料的。也许没有办法加快这个过程。关于动画,所有标记一起下降,并且对于 80 多个标记效果不佳。理想情况下,我希望它们按顺序下降。这可能吗?
  • 你不应该有 100 多个标记的问题;我的地图有数千个,直到我达到 ~4K/5K 标记我才真正开始遇到问题。即使在这些情况下,它也不会导致实际地图加载缓慢,我只看到加载和显示实际标记所需的时间问题。我在原始答案中添加了有关在 JavaScript 中添加延迟的信息。
【解决方案2】:

要按时间间隔创建标记,您可以使用 window.setTimeout(),例如:

//UNTESTED!!
            function setMarkers(map, markers) {
                   while (markers.length) {
                    var markerData = markers.shift();
                    window.setTimeout(function(){doSetMarker(markerData,map)},10);// 10 miliseconds. (play with this value).
                    }
                }

                function doSetMarker(markerData,map) {
                    var sites = markerData;
                    var siteLatLng = new google.maps.LatLng(parseFloat(sites[1]), parseFloat(sites[2]));
                    var marker = new google.maps.Marker({
                        position: siteLatLng,
                        map: map,
                        title: sites[0],
                        zIndex: sites[3],
                        html: sites[4],
                        animation: google.maps.Animation.DROP
                    });
                        var contentString = "Some content";
                        google.maps.event.addListener(marker, "click", function () {
                            infowindow.setContent(this.html);
                            infowindow.open(map, this);
                        });

                }

【讨论】:

  • 我认为这是正确的想法。不幸的是,它只产生一个标记——最后一个。我有一种感觉,这是因为它多次输出最后一个。我在上面的例子中看到变量marker 被设置了几次,我想知道这是否与某些东西冲突。我还必须将函数 doSetMarker(marker) 更改为 doSetMarker(map,marker) 以便该函数可以使用 map 变量。有什么想法吗?
  • 你是对的,因为 var 标记被设置了太多次,而且在大多数情况下它无论如何都没有标记,所以我改变了它,但我认为没有任何冲突用它。我必须建立一个页面并进行真正的尝试才能提出新的东西。我明天也许可以做到。干杯。
【解决方案3】:

TL、DR:link to demo

在我看来,您将不得不编写自定义动画函数来创建一些漂亮的东西。

我使用了开箱即用的 google.maps.Animation.DROP 和各种 setTimeout 设置,但无法找到令人满意的设置。最大的障碍似乎是同时发生的少量标记 DROP 会迅速降低动画的平滑度,从而导致丑陋、波涛汹涌、凌乱的标记雨。它甚至让我的 IE7 崩溃了 :(

换句话说,如果你想要一个好看的 DROP 序列,连续 DROP 之间的时间延迟需要比较大(100-200 毫秒),并且在 100 个标记处,这意味着等待 10 到 20 秒,直到最后一个标记下降。我认为让最终用户观看整个动画的时间太长了,但如果 DROP 延迟很短,地图的动画看起来并不好。这是动画质量和加载速度之间的平衡。

一种解决方法是向地图添加点击监听器,以便在触发时立即显示剩余的未显示标记。我的演示中没有添加这个逻辑。

这是demo on JSFiddle。可以使用三个变量,一个控制标记的数量,另外两个控制标记 DROP 之间的延迟。您可以更改这些值,然后单击 > 运行 以查看更改。

一些注意事项:

  1. 我对随机列表进行排序,以便标记从上到下下降。我认为它看起来比标记的零星雨更好。您还可以重写按距离排序的函数,以便靠近预定义中心的站点首先 DROP。

  2. 有一个自动执行的匿名函数包装超时,以便为每个标记创建新的变量范围。

【讨论】:

  • 谢谢。这正是我所需要的——我喜欢你的例子排序让动画从上到下的方式。我认为您正确地处理延迟是正确的。我将尝试一次获取不超过 50 个,如果超过 100 个则删除动画。非常感谢您的帮助。
  • 你说得对,我没有想到在超过一定限制时禁用动画。对于这些情况,您还可以考虑使用更小的标记,例如点。我发现小地图上的几百个标记会让人不知所措。
  • 只是觉得您可能对最终结果感兴趣-aotos.org.uk/directory 您可以在此链接上看到所有要点-aotos.org.uk/directory/list/singing-teachers/all-areas/by-name/… 您可以在发布的这段视频中看到它的演示在我们的年度会议上聚会-facebook.com/photo.php?v=436560903050659(4 分 20 秒)。所以,再次感谢您的帮助!
  • @iagdotme 看起来很棒!很高兴我能帮忙:)
  • 你已经很棒了。我还有一个问题,关于如何整合 map.fitBounds 以使地图适合所有标记的任何想法。刚刚注意到我只有固定缩放并以英国为中心,当缩放以适合所有标记时会很好。仅添加 bounds.extend(siteLatLng);map.fitBounds(bounds); 不起作用,因为标记位于地图之后。
猜你喜欢
  • 2013-01-14
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2013-01-27
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 2023-04-01
相关资源
最近更新 更多