谷歌地图api v3没有平滑拖动 [英] google maps api v3 no smooth dragging

查看:117
本文介绍了谷歌地图api v3没有平滑拖动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始使用maps api v3实现我的软件。不幸的是,我发现v3 API有一些严重的问题,这些问题将我从商业许可证中吸引回来。

我的客户使用高清分辨率为1920x1080的显示器,地图占用屏幕空间的90%。不幸的是,这里出现了我正在谈论的问题。当我在地图上点击鼠标并开始拖动它时,不平滑,这真的很烦人。所有的乐趣都消失了。



我使用 windows XP,windows 7和Windows 8尝试了一些不同的情节。我正在使用的浏览器是Firefox,Chrome和IE的最新版本
下面是我试图拖动地图时的结果:


  1. 小屏幕分辨率320x240:Firefox,Chrome和IE处理它很好。

  2. 小屏幕分辨率320x240,在地图上有10条折线:Chrome和IE可以很好地处理这种情况,但如果您有使用v2 API的经验你会注意到一个区别。 Firefox - 噩梦,拖拽根本不流畅。

  3. 中等屏幕分辨率1024x768。 Firefox - 有一些滞后性滞后。 Chrome浏览器和IE浏览器 - 平滑拖曳,但如果移动鼠标,速度会变得更快。

  4. 中等屏幕分辨率1024x768,在地图上有10条折线。火狐 - 恶梦。 Chrome和IE浏览器 - 你开始注意到有一些延迟,但同时它看起来很顺畅。

  5. 屏幕分辨率高达1920x1080。 Firefox - 巨大的滞后。 Chrome和IE - 稍微好一点,但仍然存在明显的滞后。
    6)屏幕分辨率高达1920x1080,地图上有折线:Firefox,Chrome ad IE - NIGHTMARE。几乎不可能拖动地图。

有趣的事实:


  1. 上述问题在google地图的v2 API中不存在。

  2. 当鼠标移动到50-60像素以下时,上述问题不存在每秒。拖动非常流畅。当鼠标快速移动时,会出现滞后现象。

  3. http:// maps。 google.com 这个问题根本不存在,但是当我在开发者处打开一些代码示例时,指导问题就在那里。以下是一个示例: https:// google-developers。 appspot.com/maps/documentation/javascript/examples/full/circle-simple

我认为我描述过问题尽可能深,无论我多么努力地绕过它,我都找不到任何解决方案。



如果有人在这个问题上分享他们的意见,我会很高兴。



PS不幸的是,我没有V2的关键,所以我不能创建一个例子,您可以查看我的本地主机外的地图,但我发现一个网站有一个并排比较(V2和V3)。尝试拖动地图看到非常不同。



http://www.wolfpil.de/v2-v3-sidebyside.html



地图的分辨率非常小,大多数可能没有经验的用户可能没有看到区别,所以我会给你提供单独的地图链接,你只需使用萤火虫或类似的debuger来使画布分辨率更大。然后你会看到我在说什么。




解决方案

同样在这里。我注意到,v3在浏览地图时触发了大量事件,浏览器往往会窒息(尤其是FF)。我这样说是因为我还使用了Bing Maps API和每秒针对 viewchange 的事件数量(相当于 center_changed in Google)要小得多。他们还提供了 addThrottledHandler()方法,可以减少生成的事件数量。

可以说,Google地图似乎针对每个 mousemove 事件并在地图视图更新之前触发了一个 center_changed 事件。所以你会得到很多生成的事件,但是没有一个会在屏幕上复制;浏览器在地图视图更新中窒息,或者可能是地图等到没有更多的更改,只有更新视图。



编辑:如果我们防止一些 mousemove 事件到达谷歌地图,然后浏览器不会窒息 mousemove 事件加上所有其他事件Google地图通过此事件生成的图像,如 center_changed ,地图将平稳过渡。 为此,我们为 #map div添加一个事件监听器(我们可以将它添加到 body 标签中)。我们添加捕获阶段的事件。当鼠标在屏幕上移动时,首先 body 标签接收事件,然后接收我们的 #map div,然后Google Maps元素(divs,瓷砖)。这是捕获阶段。在此之后,该事件将从Google Maps元素返回到我们的 #map div,然后返回到 body 标签。通常事件处理程序是为冒泡阶段注册的,所以如果我们为捕获阶段注册一个处理程序,我们可以取消事件,因此这个事件不会有冒泡阶段。这也意味着Google地图不会收到该活动。



您可以增加期间 space 参数来杀死更多事件。杀死太多事件意味着地图将开始从一个位置跳到下一个位置。杀死太少意味着所有事件都会到达谷歌地图,并且浏览器会窒息Google地图中新生成的事件,因此地图会从一个位置跳到另一个位置。一些中间地带效果最好。

现在毕竟这些Google地图不会像Bing地图那样流畅。这是因为Bing地图使用惯性:当您猛烈地移动地图时,地图将慢慢地开始跟随鼠标,然后越来越快。这确实创造了一个非常平滑的平底锅。



我发现一个有趣的事实是Google Chrome和Opera / Chrommium会生成大约一个 mousemove 事件每秒,即使鼠标不移动!这段代码也会杀死那些事件(因为距离对于这些事件是零)。

http://jsfiddle.net/uNm57/ (在Firefox中检查js控制台;你应该看到一些停止的事件,然后一个允许的事件)

 < html> 
< head>
< style type ='text / css'>
#map {
position:absolute;
宽度:100%;
身高:100%;
margin:20px;
}
< / style>

< script type ='text / javascript'>
var last = {time:new Date(),//我们上次让事件通过。
x:-100,//传递事件的最后x位置。
y:-100}; //最后的y位置是通过的事件。
var period = 100; // ms - 不要让每100ms传递一个以上的事件。
var space = 2; // px - 如果最后和
//当前位置之间的距离大于2 px,则让事件通过。

函数init_map(){
map_div = document.getElementById(map)
// map
var map_options = {
center:new google .maps.LatLng(45.836454,23.372497),
zoom:8
};
map = new google.maps.Map(document.getElementById(map),map_options);

//注册事件处理程序,用于控制事件。
//true表示我们捕获该事件,因此我们在Google地图获取之前获得事件
//。因此,如果我们取消该活动,
// Google地图将永远不会收到。
map_div.addEventListener(mousemove,throttle_events,true);
};

function throttle_events(event){
var now = new Date();
var distance = Math.sqrt(Math.pow(event.clientX - last.x,2)+ Math.pow(event.clientY - last.y,2));
var time = now.getTime() - last.time.getTime();
if(distance * time console.log(event stopped);
if(event.stopPropagation){// W3C / addEventListener()
event.stopPropagation();
} else {//较老的IE。
event.cancelBubble = true;
};
} else {
console.log(event allowed:+ now.getTime());
last.time = now;
last.x = event.clientX;
last.y = event.clientY;
};
};
< / script>
< / head>
< body onload =init_map()>
< div id =map>< / div>
< / body>
< / html>


I started implementing my software using maps api v3. Unfortunatelly i found out that v3 API has some serious issues which draws me back from bying a bussiness licence.

My clients use monitors with HD resolution which is 1920x1080 and the map takes 90% of the screen space. Unfortunatelly here comes the problem i am talking about. When i click with the mouse on the map and start dragging it it is not smootly and it is really annoying. All the fun goes away.

I tried some different scenarious using windows XP, windows 7 and Windows 8. The browsers i am working with are the latest versions of Firefox, Chrome and IE. Here are the results when i try to drag the map:

  1. Small screen resolution 320x240: Firefox, Chrome and IE handle it very well. It is impossible to notice that the dragging is not smooth.
  2. Small screen resolution 320x240 with 10 polylines on the map: Chrome and IE handle it kind of well but if you have experience with v2 API you will notice a difference. Firefox - nightmare, dragging is not smooth at all.
  3. Medium screen resolution 1024x768. Firefox - there is some incosistent lagging. Chrome and IE - kind of smooth dragging but if you move the mouse fast things get worse.
  4. Medium screen resolution 1024x768 with 10 polylines on the map. Firefox - nightmare. Chrome and IE - you start to notice that there is some delay but at the same time it looks kind of smooth.
  5. High screen resolution 1920x1080. Firefox - huge lagging. Chrome and IE - a little better but still there is a noticeble lagging. 6) High screen resolution 1920x1080 with polylines on the map: Firefox, Chrome ad IE - NIGHTMARE. It is almost impossible to drag the map.

Interesting facts:

  1. The problem described above does not exists with v2 API of google maps.
  2. The problem described above does not exists when the mouse is moved less than 50-60 pixels per second. Dragging is really smooth. When the mouse is beeing moved fast the lagging appears.
  3. On http://maps.google.com the problem does not exists at all BUT when i open some of the code samples on developers guide the problem is there. Here is an example: https://google-developers.appspot.com/maps/documentation/javascript/examples/full/circle-simple.

I think that i described the problem as deep as possible and no matter how hard i tried to bypass it i could not find any solution.

I will be glad if somebody shares their opinion on this problem.

P.S. Unfortunatelly i do not have a key for v2 so i can not create an example where you can view the map outside my localhost but i found a web site where there is a side by side comparison (v2 and v3). Try dragging the maps to see the VERY difference.

http://www.wolfpil.de/v2-v3-sidebyside.html

The resolution of the maps is very small and most probably unexperienced users may not see the difference so i will give you also the seperate links to the maps and you just have to use firebug or a similar debuger to make the canvas resolution bigger. Then you will see what i am talking about.

解决方案

Same here. What I noticed is that v3 fires a lot of events while panning the map and the browser tends to choke (FF especially). I say this because I also used Bing Maps API and the number of events per second for viewchange (equivalent for center_changed in Google) is much smaller. Also they provide the method addThrottledHandler() with which you can reduce the number of events generated.

From what I can tell, Google Maps seem to fire one center_changed event for each mousemove event and before the map's view is updated. So you get a lot of events generated but none of them are replicated on the screen; browser chokes on map view updates or it might be that the map waits until there are no more changes and only then it updates the view.

Edit: if we prevent some of the mousemove events to reach Google Maps then the browser will not choke on mousemove events plus all the other events that Google Maps generates from this event, like center_changed, and the map will pan smoothly.

To do this we add an event listener to the #map div (we can add it to body tag also). We add the event for the capture phase. When mouse moves on the screen, first the body tag receives the event then our #map div and then Google Maps elements (divs, tiles). This is the capture phase. After that follows the bubble phase in which the event goes back from Google Maps elements to our #map div and then to the body tag. Usually event handlers are registered for the bubbling phase so if we register a handler for the capture phase we can cancel the event and so there will be no bubbling phase for this event. This also means that Google Maps will not receive the event.

You can increase the period and space parameters to kill more events. Killing too many events means that the map will start to jump from one position to the next. Killing too few means that all events will reach Google Maps and the browser will choke on newly generated events from Google Maps and so the map will jump from one position to the next. Some middle ground works best.

Now after all these, Google Maps will not be as smooth as Bing Maps. This is because Bing Maps use inertia: when you move the map violently, the map will start slowly to follow the mouse and then faster and faster. This creates a very smooth pan indeed.

An interesting fact that I've found is that Google Chrome and Opera/Chrommium will generate about one mousemove event per second even if the mouse doesn't move! This code will kill those events too (because distance is zero for those events).

http://jsfiddle.net/uNm57/ (check js console in Firefox; you should see some events that are stopped and then one allowed event)

<html>
  <head>
    <style type='text/css'>
      #map {
          position: absolute;
          width: 100%;
          height: 100%;
          margin: 20px;
      }
    </style>

    <script type='text/javascript'>
      var last = {time : new Date(),    // last time we let an event pass.
                  x    : -100,          // last x position af the event that passed.
                  y    : -100};         // last y position af the event that passed.
      var period = 100; // ms - don't let pass more than one event every 100ms.
      var space  = 2;   // px - let event pass if distance between the last and
                        //      current position is greater than 2 px.

      function init_map() {
          map_div = document.getElementById("map")
          // map
          var map_options = {
              center: new google.maps.LatLng(45.836454, 23.372497),
              zoom: 8
          };
          map = new google.maps.Map(document.getElementById("map"), map_options);

          // register event handler that will throttle the events.
          // "true" means we capture the event and so we get the event
          // before Google Maps gets it. So if we cancel the event,
          // Google Maps will never receive it.
          map_div.addEventListener("mousemove", throttle_events, true);
      };

      function throttle_events(event) {
          var now = new Date();
          var distance = Math.sqrt(Math.pow(event.clientX - last.x, 2) + Math.pow(event.clientY - last.y, 2));
          var time = now.getTime() - last.time.getTime();
          if (distance * time < space * period) {    //event arrived too soon or mouse moved too little or both
              console.log("event stopped");
              if (event.stopPropagation) { // W3C/addEventListener()
                  event.stopPropagation();
              } else { // Older IE.
                  event.cancelBubble = true;
              };
          } else {
              console.log("event allowed: " + now.getTime());
              last.time = now;
              last.x    = event.clientX;
              last.y    = event.clientY;
          };
      };
    </script>
</head>
<body onload = "init_map()">
    <div id="map"></div>
</body>
</html>

这篇关于谷歌地图api v3没有平滑拖动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆