最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Replacing GTileLayer in Google Maps v3, with ImageMapType, Tile bounding box? - Stack Overflow

programmeradmin3浏览0评论

I need to update this code:

radar_layer.getTileUrl=function(tile,zoom) {

    var llp = new GPoint(tile.x*256,(tile.y+1)*256);
    var urp = new GPoint((tile.x+1)*256,tile.y*256);
    var ll = G_NORMAL_MAP.getProjection().fromPixelToLatLng(llp,zoom);
    var ur = G_NORMAL_MAP.getProjection().fromPixelToLatLng(urp,zoom);
    var dt = new Date();
    var nowtime = dt.getTime();

    var tileurl = ".cgi?";
        tileurl+="bbox="+ll.lng()+","+ll.lat()+","+ur.lng()+","+ur.lat();
        tileurl+="&width=256&height=256&reaspect=false&cachetime="+nowtime;

    return tileurl;
};

I got as far as:

var DemoLayer = new google.maps.ImageMapType({

     getTileUrl: function(coord, zoom) {

     var llp = new google.maps.Point(coord.x*256,(coord.y+1)*256);
     var urp = new google.maps.Point((coord.x+1)*256,coord.y*256);
     var ll = googleMap.getProjection().fromPointToLatLng(llp);
     var ur = googleMap.getProjection().fromPointToLatLng(urp);
     var dt = new Date();
     var nowtime = dt.getTime();

     var tileurl = ".cgi?";
         tileurl+="bbox="+ll.lng()+","+ll.lat()+","+ur.lng()+","+ur.lat();
  tileurl+="&width=256&height=256&reaspect=false&cachetime="+nowtime;

     return tileurl;

     },
             tileSize: new google.maps.Size(256, 256),
             opacity:1.0,
             isPng: true
         });

Specifically, I need help with this section:

var llp = new google.maps.Point(coord.x*256,(coord.y+1)*256);
 var urp = new google.maps.Point((coord.x+1)*256,coord.y*256);
 var ll = googleMap.getProjection().fromPointToLatLng(llp);
 var ur = googleMap.getProjection().fromPointToLatLng(urp);

The service wants the tile bounding box from what I understand. However, ll and ur do not seem to correct at all.

I had it working and displaying the entire map bounding box in each tile, but of course that's not what I need.

Any insight here would be greatly appreciated, not having the GTileLayers in V3 is fine if I can work around it, until then I'm frustrated.

I need to update this code:

radar_layer.getTileUrl=function(tile,zoom) {

    var llp = new GPoint(tile.x*256,(tile.y+1)*256);
    var urp = new GPoint((tile.x+1)*256,tile.y*256);
    var ll = G_NORMAL_MAP.getProjection().fromPixelToLatLng(llp,zoom);
    var ur = G_NORMAL_MAP.getProjection().fromPixelToLatLng(urp,zoom);
    var dt = new Date();
    var nowtime = dt.getTime();

    var tileurl = "http://demo.remoteservice.com/cgi-bin/serve.cgi?";
        tileurl+="bbox="+ll.lng()+","+ll.lat()+","+ur.lng()+","+ur.lat();
        tileurl+="&width=256&height=256&reaspect=false&cachetime="+nowtime;

    return tileurl;
};

I got as far as:

var DemoLayer = new google.maps.ImageMapType({

     getTileUrl: function(coord, zoom) {

     var llp = new google.maps.Point(coord.x*256,(coord.y+1)*256);
     var urp = new google.maps.Point((coord.x+1)*256,coord.y*256);
     var ll = googleMap.getProjection().fromPointToLatLng(llp);
     var ur = googleMap.getProjection().fromPointToLatLng(urp);
     var dt = new Date();
     var nowtime = dt.getTime();

     var tileurl = "http://demo.remoteservice.com/cgi-bin/serve.cgi?";
         tileurl+="bbox="+ll.lng()+","+ll.lat()+","+ur.lng()+","+ur.lat();
  tileurl+="&width=256&height=256&reaspect=false&cachetime="+nowtime;

     return tileurl;

     },
             tileSize: new google.maps.Size(256, 256),
             opacity:1.0,
             isPng: true
         });

Specifically, I need help with this section:

var llp = new google.maps.Point(coord.x*256,(coord.y+1)*256);
 var urp = new google.maps.Point((coord.x+1)*256,coord.y*256);
 var ll = googleMap.getProjection().fromPointToLatLng(llp);
 var ur = googleMap.getProjection().fromPointToLatLng(urp);

The service wants the tile bounding box from what I understand. However, ll and ur do not seem to correct at all.

I had it working and displaying the entire map bounding box in each tile, but of course that's not what I need.

Any insight here would be greatly appreciated, not having the GTileLayers in V3 is fine if I can work around it, until then I'm frustrated.

Share Improve this question asked May 26, 2010 at 19:07 justdevjustdev 1711 gold badge1 silver badge7 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 12

The fix in my case was to use an updated tile service from the same publisher. It accepts simpler paramaters:

   globalfoovar = new google.maps.ImageMapType({
    getTileUrl: function(tile, zoom) {
        return "http://bar.com/" + zoom + "/" + tile.x + "/" + tile.y +".png"; 
    },
    tileSize: new google.maps.Size(256, 256),
    opacity:0.60,
    isPng: true
});

googleMap.overlayMapTypes.push(null); // create empty overlay entry
googleMap.overlayMapTypes.setAt("0",globalfoovar); // set the overlay, 0 index

// if you want to hide the layer later (toggle):
// googleMap.overlayMapTypes.setAt("0",null);

As you can see, this is much easier than the code I posted in the problem description.

However if you're still reading you probably still want the answer to the original problem, which is converting latlng to pixels. Don't worry, I have a solution for that as well.

To gain access to the 4 useful latlng, point, and pixel conversions you need to add a dummy OverlayView.

Step 1) Define the stub so it is globally available, along with your map and other vars:

var googleMap = {}; // global map var
var mapCanvasStub = {}; // map OverlayView var

Step 2) After you render your map, setup this dummy/stub OverlayView like so:

googleMap = new google.maps.Map($('#mapCanvas')[0]); // google map init

mapCanvasStub = function (map) { this.setMap(map); }  // start building overlay stub
mapCanvasStub.prototype = new google.maps.OverlayView(); 
mapCanvasStub.prototype.draw = function() {}; 
mapCanvasStub = new mapCanvasStub(googleMap); // bin dthe overlay to the map

Now you've got a functional OverlayView tied to the map, whenever you need to use those conversions you can do so like this:

var projection = mapCanvasStub.getProjection();
var position = projection.fromLatLngToContainerPixel( latLng );
                   // or fromContainerPixelToLatLng()
                   // or fromDivPixelToLatLng()
                   // or fromLatLngToDivPixel()
                   // or fromLatLngToDivPixel()

In my case I'm using this to create custom info bubbles, here is a snippet from my click event:

function customAlertClick(a,b,c) {

    var projection = mapCanvasStub.getProjection();
    var position = projection.fromLatLngToContainerPixel(b);
    var top = (position.y + parseInt($('#mapCanvas').position().top));
    var lft = (position.x + parseInt($('#mapCanvas').position().left));

    // obviously this is an overly simple example
    $('#foo').css('top',top + 'px');
    $('#foo').css('lft',left + 'px');
}

Hope this helps anyone else making the jump to V3.

If you're wondering why we have to jump through these extra hoops to do something that is so simple in V2, the answer is pretty obvious when you think about it. V3 is setup to work well on mobile devices where bandwidth and cpu power are limited. They've eliminated as much code as possible to get the simple maps rendering, and they expect you to manually wire up these extras if you absolutely need them.

If I had more time I'd write a sample.html but this should get you going.

Thank you for the details. In fact in my case I couldn't change the API to use tiles number I need to pass LatLng. I found this solution... so far it works for me:

var myMapOptions = {
          getTileUrl: function(coord,zoom) { 
            var proj = map.getProjection();
            var zfactor=Math.pow(2,zoom);
            var top=proj.fromPointToLatLng(new google.maps.Point(coord.x*256/zfactor,coord.y*256/zfactor));
            var bot=proj.fromPointToLatLng(new google.maps.Point((coord.x+1)*256/zfactor,(coord.y+1)*256/zfactor));
            url = "/layer/layer_"+zoom+"_"+top.lng().toFixed(6)+"_"+bot.lat().toFixed(6)+"_"+bot.lng().toFixed(6)+"_"+top.lat().toFixed(6)+".png";
        return url; 
       },
      tileSize: new google.maps.Size(256, 256),
      isPng: true,
      opacity: 0.4
     }

It's worked for me

I used MapBox.Light Style Tileset on the top of Google API V3

function loadMap() {
    // Default the map view to the continental U.S.
    mapOptions = {
      center: new google.maps.LatLng(17.387140, 78.491684),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      zoom: 8
    };

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

    var imageMapType = new google.maps.ImageMapType({
      getTileUrl: function(coord, zoom) {
        return "https://api.mapbox.com/v4/mapbox.light/" +zoom+"/"+coord.x+"/"+coord.y+"@2x.png?access_token=<<access_token>>";

      },
      tileSize: new google.maps.Size(256, 256)
    });

    map.overlayMapTypes.push(imageMapType);        

}

loadMap();

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论