diff --git a/README.md b/README.md index 7a758c6..df6ab79 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Option | Type | Default | Description `tileFormat` | `String` | `'jpg'` | The [format](http://iiif.io/api/image/2.0/#format) of the returned image. `tileSize` | Number | 256 | Tile size (width and height in pixels, assuming tiles are square). `fitBounds` | Boolean | true | Automatically center and fit the maps bounds to the added IIIF layer +`setMaxBounds` | Boolean | false | Constrain the map viewer to the image `quality` | String | 'default' | [determines whether the image is delivered in color, grayscale or black and white](http://iiif.io/api/image/2.0/#quality) _Note:_ All IIIF servers do not support this parameter. ### Development diff --git a/leaflet-iiif.js b/leaflet-iiif.js index ee5ae09..00b399c 100644 --- a/leaflet-iiif.js +++ b/leaflet-iiif.js @@ -10,7 +10,8 @@ L.TileLayer.Iiif = L.TileLayer.extend({ tileSize: 256, updateWhenIdle: true, tileFormat: 'jpg', - fitBounds: true + fitBounds: true, + setMaxBounds: false }, initialize: function(url, options) { @@ -75,6 +76,10 @@ L.TileLayer.Iiif = L.TileLayer.extend({ _this._fitBounds(); } + if(_this.options.setMaxBounds) { + _this._setMaxBounds(); + } + // Reset tile sizes to handle non 256x256 IIIF tiles _this.on('tileload', function(tile, url) { @@ -90,6 +95,18 @@ L.TileLayer.Iiif = L.TileLayer.extend({ }); }); }, + onRemove: function(map) { + var _this = this; + + // Remove maxBounds set for this image + if(_this.options.setMaxBounds) { + map.setMaxBounds(null); + } + + // Call remove TileLayer + L.TileLayer.prototype.onRemove.call(_this, map); + + }, _fitBounds: function() { var _this = this; @@ -102,6 +119,18 @@ L.TileLayer.Iiif = L.TileLayer.extend({ _this._map.fitBounds(bounds, true); }, + _setMaxBounds: function() { + var _this = this; + + // Find best zoom level, center map, and constrain viewer + var initialZoom = _this._getInitialZoom(_this._map.getSize()); + var imageSize = _this._imageSizes[initialZoom]; + var sw = _this._map.options.crs.pointToLatLng(L.point(0, imageSize.y), initialZoom); + var ne = _this._map.options.crs.pointToLatLng(L.point(imageSize.x, 0), initialZoom); + var bounds = L.latLngBounds(sw, ne); + + _this._map.setMaxBounds(bounds, true); + }, _getInfo: function() { var _this = this; diff --git a/spec/LTileLayerIiifSpec.js b/spec/LTileLayerIiifSpec.js index 24e04f9..139d26f 100644 --- a/spec/LTileLayerIiifSpec.js +++ b/spec/LTileLayerIiifSpec.js @@ -186,4 +186,36 @@ describe('L.TileLayer.Iiif', function() { }); }); + + describe('setMaxBounds', function() { + var iiifLayer; + + beforeEach(function() { + iiifLayer = iiifLayerFactory(); + }); + + afterEach(function() { + iiifLayer.off('load'); + }); + + it('by default is off', function(done) { + map.addLayer(iiifLayer); + iiifLayer.on('load', function() { + expect(iiifLayer.options.setMaxBounds).toBe(false); + expect(map.options.maxBounds).toBe(undefined); // documentation says default should be null? + done(); + }); + }); + + it('can be configured to be on', function(done) { + var iiifLayerSetMaxBounds = iiifLayerFactory({ setMaxBounds: true }); + map.addLayer(iiifLayerSetMaxBounds); + iiifLayerSetMaxBounds.on('load', function() { + expect(iiifLayerSetMaxBounds.options.setMaxBounds).toBe(true); + expect(map.options.maxBounds.getSouthWest().toString()).toBe('LatLng(-478, 0)'); + expect(map.options.maxBounds.getNorthEast().toString()).toBe('LatLng(0, 679)'); + done(); + }); + }); + }); });