jjzjj

javascript - 刷新 GoogleMaps tile 服务器在 JavaScript 中有效,但在 GWT 中无效

coder 2024-03-08 原文

我在 GWT 应用程序中显示天气图。我正在使用 GWT 2.7 和可用的 GoogleMaps JavaScript API 的 GWT 包装器 here (gwt-maps-3.8.0-pre1.zip)。

我使用磁贴服务器获取天气,它每 5 分钟更新一次。在 5 分钟标记处,我通过将缩放比例设置为 1 然后恢复到原始状态、触发调整大小以及删除然后再次添加天气图层来刷新 map 。

这很好用。但是,最近我注意到这不再有效:刷新甚至不会进入磁贴服务器,因此不会显示新的天气。如果您将我的 map 放置 12 小时,您将看到 12 小时前的天气。以前, map 会自动保持更新。我没有更改任何代码。 所以我的猜测是底层 GoogleMaps JavaScript API 发生了一些变化。

但是,我随后创建了这个简单的纯 JavaScript 示例:

<!DOCTYPE html>
<html>
    <head>
        <title>Map Test</title>
        <style type="text/css">
            html, body { height: 100%; margin: 0; padding: 0; }
            #map {
                width:90%;
                height: 90%;
                display:inline-block;
            }
        </style>
    </head>
<body>
<div id="map"></div>
<button type="button" onClick="refreshMap()">Refresh</button>
<script type="text/javascript">

    var map;
    var tileNEX;

    function initMap() {

        var mapOptions = {
            zoom: 8,
            center: new google.maps.LatLng(42.5, -95.5),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        map = new google.maps.Map(document.getElementById('map'), mapOptions);

        tileNEX = new google.maps.ImageMapType({
            getTileUrl: function(tile, zoom) {
                return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/" + zoom + "/" + tile.x + "/" + tile.y +".png?"+ (new Date()).getTime(); 
            },
            tileSize: new google.maps.Size(256, 256),
            opacity:0.60,
            name : 'NEXRAD',
            isPng: true
        });

        map.overlayMapTypes.setAt("0",tileNEX);
    }

    function refreshMap(){
        var zoom = map.getZoom();
        map.setZoom(1);
        map.setZoom(zoom);

        //google.maps.event.trigger(map, 'resize');

        //var layer = map.overlayMapTypes.getAt(0);
    //map.overlayMapTypes.setAt(0, null);
    //map.overlayMapTypes.setAt(0, layer);
    }

</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
</body>
</html>

令我惊讶的是,这仍然可以正常工作。每当您单击“刷新”按钮时, map 都会转到切片服务器并获取新切片。

所以我尝试在 GWT 中做完全相同的事情:

package com.example.client;

import com.google.gwt.ajaxloader.client.AjaxLoader;
import com.google.gwt.ajaxloader.client.AjaxLoader.AjaxLoaderOptions;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.maps.gwt.client.GoogleMap;
import com.google.maps.gwt.client.LatLng;
import com.google.maps.gwt.client.MapOptions;
import com.google.maps.gwt.client.MapType;
import com.google.maps.gwt.client.MapTypeId;

public class GwtMapTest implements EntryPoint {

    @Override
    public void onModuleLoad() {
        AjaxLoaderOptions options = AjaxLoaderOptions.newInstance();
        options.setOtherParms("sensor=false");
        Runnable callback = new Runnable() {
            public void run() {
                createMap();
            }
        };
        AjaxLoader.loadApi("maps", "3", callback, options);
    }

    public void createMap() {

        MapOptions mapOpts = MapOptions.create();
        mapOpts.setZoom(4);
        mapOpts.setCenter(LatLng.create(37.09024, -95.712891));
        mapOpts.setMapTypeId(MapTypeId.TERRAIN);
        mapOpts.setStreetViewControl(false);

        final GoogleMap map = GoogleMap.create(Document.get().getElementById("map_canvas"), mapOpts);
        addWeatherLayer(map);   

        Button button = new Button("Gwt Refresh");
        button.addClickHandler(new ClickHandler(){

            @Override
            public void onClick(ClickEvent event) {
                refreshWeatherLayer(map);
            }
        });

        Button nativeButton = new Button("Native Refresh");
        nativeButton.addClickHandler(new ClickHandler(){

            @Override
            public void onClick(ClickEvent event) {
                nativeRefreshWeatherLayer(map);
            }
        });

        RootPanel.get().add(button);
        RootPanel.get().add(nativeButton);
    }

    public native void addWeatherLayer(GoogleMap map) /*-{
        var imageMapType = new $wnd.google.maps.ImageMapType({
            getTileUrl: function(coord, zoom) {
                return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/"+ zoom + "/" + coord.x + "/" + coord.y + ".png";
            },
            tileSize: new $wnd.google.maps.Size(256, 256),
            opacity:.50,
            isPng: true
        });

        map.overlayMapTypes.setAt("0", imageMapType);

    }-*/;

    private void refreshWeatherLayer(GoogleMap map){
        double zoom = map.getZoom();
        map.setZoom(1);
        map.setZoom(zoom);

        MapType layer = map.getOverlayMapTypes().getAt(0);
        map.getOverlayMapTypes().setAt(0, null);
        map.getOverlayMapTypes().setAt(0, layer);
    }

    private native void nativeRefreshWeatherLayer(GoogleMap map) /*-{
        var zoom = map.getZoom();
        map.setZoom(1);
        map.setZoom(zoom);

        $wnd.google.maps.event.trigger(map, 'resize');

        var layer = map.overlayMapTypes.getAt(0);
        map.overlayMapTypes.setAt(0, null);
        map.overlayMapTypes.setAt(0, layer);
    }-*/;

}

这应该与纯 JavaScript 示例做同样的事情。相反,当我单击该按钮时, map 会刷新(我看到天气图层闪烁),但它实际上并没有转到切片服务器以获取新切片

更奇怪的是,这种“分类”在 Internet Explorer 中有效:也许我点击按钮 3 次中有 1 次, map 实际上进入了切片服务器。但在 Chrome 中,当我点击按钮时,它永远不会进入磁贴服务器。

为了确定这一点,我正在查看浏览器工具的网络选项卡。 我希望每次单击按钮时 map 都能访问切片服务器。这就是它在纯 JavaScript 中所做的,这也是它过去在 GWT 中所做的,但在过去几个月的某个时候GWT 行为已更改。

我不认为这是浏览器缓存问题。问题是不是 map 试图获取新图 block 但得到旧图 block ,而是它永远不会尝试获取新的图 block 。我单击该按钮,但在开发人员工具的网络选项卡中没有看到任何变化。

  • 为什么我在 JavaScript 和 GWT 中看到不同的行为?
  • 为什么我会在不同的浏览器中看到不同的行为?
  • GWT GoogleMaps 库是否在进行某种内部缓存?有没有办法禁用它?
  • 为什么这种行为明显改变了?
  • 如何通过转到切片服务器获取新切片来刷新 GWT map ?

最佳答案

这不是最终答案。但包含重要信息。

为了管理 http 调用,GWT 有一组像浏览器一样工作的类,这就是我认为的问题所在。

如果之前使用的相同代码可能是切片服务器最近包含缓存 header (Cache-Control:max-age=300)。由于某些原因,GWT 代码没有正确管理此 header 。

如果我是对的,解决问题的一种方法是在 GWT 调用中附加一个带有当前时间的参数(就像代码的浏览器版本一样)。

public native void addWeatherLayer(GoogleMap map) /*-{
    var imageMapType = new $wnd.google.maps.ImageMapType({
        getTileUrl: function(coord, zoom) {
            return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/"+ zoom + "/" + coord.x + "/" + coord.y + ".png?" + new Date().getTime();
        },
        tileSize: new $wnd.google.maps.Size(256, 256),
        opacity:.50,
        isPng: true
    });

    map.overlayMapTypes.setAt("0", imageMapType);

}-*/;

关于javascript - 刷新 GoogleMaps tile 服务器在 JavaScript 中有效,但在 GWT 中无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37194140/

有关javascript - 刷新 GoogleMaps tile 服务器在 JavaScript 中有效,但在 GWT 中无效的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  8. python - 是否可以使用 Ruby 或 Python 禁用 anchor /引用来发出有效的 YAML? - 2

    是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案

  9. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  10. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

随机推荐