[OpenLayers-Users] Static images, bounds and zoom

Florian Klumb Florian.Klumb at rwth-aachen.de
Thu Dec 11 09:27:21 EST 2008


OK, I figured it out.

For the record, here's a small how-to (maybe someone as unfamiliar with OL like me will find it useful)

Bounds: it doesn't really matter what you choose as your map extent (it just needs to have the correct aspect ratio (AR), let's call it img.AR, and if you care that the center of the image coincides with the center of the viewport, you have to specify accordingly since the center of the coordinate system [map units] actually is at the map center not at a corner ), so for my 8000x4000 image I use
new OpenLayers.Bounds(-2, -1, 2, 1) // correct AR and image centered

Size: fit your image to the viewport, i.e. wait for the DOM to be ready, calculate the viewport AR  (in the example case the map's resolution is 707x400, i.e. map.AR=1.76), and set the size of the image accordingly:

map.AR < img.AR => imgLayer.width = map.width => imgLayer.height = imgLayer.width / img.AR
map.AR > img.AR => imgLayer.height= map.height => imgLayer.width= imgLayer.height * img.AR

In the example, I use
new OpenLayers.Size(707, 353)

minResolution determines the higest zoom level, hence if we want to zoom until a natural resolution is reached, minResolution = bounds.width / img.width (minResolution = bounds.height / img.height  works as well since bounds has a correct AR).
Additionally, it's possible to set numZoomLevels to determine how many steps between the max and min resolution can be taken, e.g.
numZoomLevels: 10


So, the code would be:

var map= new OpenLayers.Map('map',
var layer = new OpenLayers.Layer.Image(
  'City Lights',
  'images/political_world_map.jpg',  // which is 8000x4000pxs
  new OpenLayers.Bounds(-2, -1, 2, 1),
  new OpenLayers.Size(707, 353),
  {
      minResolution: 4 / 8000,
      numZoomLevels: 10
  }
);
map.addLayers([layer]);
map.zoomToMaxExtent();

A problem arises though when the viewport is resized (e.g. by a window resize). Resolutions would have to be adjusted but according to a posting from Christopher in January 2007 this does not work [http://www.nabble.com/Re%3A-Can-I-make-the-map-cover-the-whole-viewport-p8552184.html]. Or have there been changes? I'd be really interested to hear about that!

Flo

> Hi,
> 
> Li, thanks very much for the patch, as far as I can judge it corrects 
> an annoying aspect ratio issue. That's very helpful indeed!
> 
> Still, how do I now adjust the zoom level to allow users zoom in until 
> the natural image resolution is reached? Could anyone please give me a 
> hint?
> 
> Flo
> 
> > You can use below patch:
> > 
> > Index: lib/OpenLayers/Layer/Image.js
> > ===================================================================
> > --- lib/OpenLayers/Layer/Image.js    (revision 8489)
> > +++ lib/OpenLayers/Layer/Image.js    (working copy)
> > @@ -47,13 +47,6 @@
> >      tile: null,
> > 
> >      /**
> > -     * Property: aspectRatio
> > -     * {Float} The ratio of height/width represented by a single 
> > pixel in
> > the
> > -     * graphic
> > -     */
> > -    aspectRatio: null,
> > -
> > -    /**
> >       * Constructor: OpenLayers.Layer.Image
> >       * Create a new image layer
> >       *
> > @@ -69,9 +62,6 @@
> >          this.extent = extent;
> >          this.size = size;
> >          OpenLayers.Layer.prototype.initialize.apply(this, [name, options]);
> > -
> > -        this.aspectRatio = (this.extent.getHeight() / this.size.h) 
> /
> > -                           (this.extent.getWidth() / this.size.w);
> >      },
> > 
> >      /**
> > @@ -128,9 +118,9 @@
> >           * image will be stretched in one dimension only.
> >           */
> >          if( this.options.maxResolution == null ) {
> > -            this.options.maxResolution = this.aspectRatio *
> > -                                         this.extent.getWidth() /
> > -                                         this.size.w;
> > +            var wRes = this.extent.getWidth() / this.size.w;
> > +            var hRes = this.extent.getHeight() / this.size.h;
> > +            this.options.maxResolution = Math.min(wRes, hRes);
> >          }
> >          OpenLayers.Layer.prototype.setMap.apply(this, arguments);
> >      },
> > @@ -155,8 +145,10 @@
> >              this.setTileSize();
> > 
> >              //determine new position (upper left corner of new bounds)
> > -            var ul = new OpenLayers.LonLat(this.extent.left,
> > this.extent.top);
> > -            var ulPx = this.map.getLayerPxFromLonLat(ul);
> > +            var center = this.extent.getCenterLonLat();
> > +            var centerPx = this.map.getLayerPxFromLonLat(center);
> > +            var ulPx = new OpenLayers.Pixel(centerPx.x - 
> > (this.tileSize.w /
> > 2),
> > +                     centerPx.y - (this.tileSize.h / 2));
> > 
> >              if(firstRendering) {
> >                  //create the new tile
> > @@ -175,10 +167,23 @@
> >       * Set the tile size based on the map size.
> >       */
> >      setTileSize: function() {
> > -        var tileWidth = this.extent.getWidth() / this.map.getResolution();
> > -        var tileHeight = this.extent.getHeight() /
> > this.map.getResolution();
> > -        this.tileSize = new OpenLayers.Size(tileWidth, tileHeight);
> > +        var w = this.extent.getWidth() / this.map.getResolution();
> > +        var h = this.extent.getHeight() / this.map.getResolution();
> > +
> > +        this.tileSize = this.getLockedSize(w, h);
> >      },
> > +
> > +    getLockedSize: function(w, h) {
> > +        var tileWidth = w;
> > +        var tileHeight = h;
> > +        if(this.size.h > this.size.w) {
> > +            tileHeight = Math.floor(this.size.h * (w / this.size.w));
> > +        } else {
> > +            tileWidth = Math.floor(this.size.w * (h / this.size.h));
> > +        }
> > +
> > +        return new OpenLayers.Size(tileWidth, tileHeight);
> > +    },
> > 
> >      /**
> >       * APIMethod: setUrl
> > 
> > If this is the right way for the image layer, I will open a ticket 
> for 
> > this
> > patch.
> > 
> > 
> > > Hi,
> > >
> > > I'm using OpenLayers to develop a viewing application for medical 
> images.
> > > So far I'm just using static images, i.e. I'm using the Image 
> layer, 
> > and I'm
> > > a bit puzzled as to the interdependence of bounds, extent, 
> > resolution and
> > > all this stuff. I simply want to fit an image which might be quite 
> high-res
> > > into the viewport for a start and then let the users zoom in until 
> the
> > > natural resolution of the image is reached. I played with all the 
> parameters
> > > but to be honest I still haven't quite gotten the gist, so even 
> > after hours
> > > it seems as if I'm not a step further. A hint or short explanation 
> 
> > as to how
> > > to approach this would be greatly appreciated!
> > >
> > > My code is something like this:
> > > var oMapWest = new OpenLayers.Map('viewportWest');
> > > var graphic = new OpenLayers.Layer.Image(
> > >  'City Lights',
> > >  'images/political_world_map.jpg',  // which is 8000x4000pxs
> > >  new OpenLayers.Bounds(-180, -90, 180, 90),
> > >  new OpenLayers.Size(700, 350),
> > >  {numZoomLevels:10}
> > > );
> > > oMapWest.addLayers([graphic]);
> > > oMapWest.zoomToMaxExtent();
> > >
> > > Thanks!
> > >
> > > Flo
> > >
> > >
> > 
> > 
> > -- 
> > Li XinGang
> > EMail: slinavlee at gmail.com
> > Blog:   avlee.cnblogs.com
> > Site:    www.mapboost.org.cn
> > _______________________________________________
> > Users mailing list
> > Users at openlayers.org
> > http://openlayers.org/mailman/listinfo/users
> _______________________________________________
> Users mailing list
> Users at openlayers.org
> http://openlayers.org/mailman/listinfo/users






More information about the Users mailing list