diff --git a/build/docs.sh b/build/docs.sh index 2877c613c5..3ec415f1c3 100755 --- a/build/docs.sh +++ b/build/docs.sh @@ -1,7 +1,7 @@ #!/bin/sh rm ../doc/reference.html -CLASSES="Map Layer Layer.HTTPRequest Layer.Grid Layer.WMS Layer.KaMap Layer.EventPane Layer.Google Layer.VirtualEarth Layer.Markers Layer.Text Layer.GeoRSS Layer.Boxes Icon Marker Marker.Box Tile Tile.Image Tile.WFS Control Control.LayerSwitcher Control.MouseDefaults Control.MousePosition Control.MouseToolbar Control.OverviewMap Control.PanZoom Control.PanZoomBar Control.Permalink Control.Scale LonLat Size Pixel Bounds Util Ajax" +CLASSES="Map Layer Layer.Image Layer.HTTPRequest Layer.Grid Layer.WMS Layer.KaMap Layer.EventPane Layer.Google Layer.VirtualEarth Layer.Markers Layer.Text Layer.GeoRSS Layer.Boxes Icon Marker Marker.Box Tile Tile.Image Tile.WFS Control Control.LayerSwitcher Control.MouseDefaults Control.MousePosition Control.MouseToolbar Control.OverviewMap Control.PanZoom Control.PanZoomBar Control.Permalink Control.Scale LonLat Size Pixel Bounds Util Ajax" echo " OpenLayers Class Reference Documentation diff --git a/examples/image-layer.html b/examples/image-layer.html new file mode 100644 index 0000000000..25ed41f2cd --- /dev/null +++ b/examples/image-layer.html @@ -0,0 +1,51 @@ + + + + + + + +

OpenLayers Image Layer Example

+
+

+ The "City Lights" layer above is created from a single web accessible + image. If you construct it without any resolution related options, + the layer will be given a single resolution based on the extent/size. + Otherwise, it behaves much like a regular layer. This is primarily + intended to be used in an overview map - where another layer type + might not make a good overview. +

+ + diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 94f9686db3..5ccb0ce5ca 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -65,6 +65,7 @@ if (typeof(_OPENLAYERS_SFL_) == "undefined") { "OpenLayers/Feature/WFS.js", "OpenLayers/Tile/Image.js", "OpenLayers/Tile/WFS.js", + "OpenLayers/Layer/Image.js", "OpenLayers/Layer/EventPane.js", "OpenLayers/Layer/FixedZoomLevels.js", "OpenLayers/Layer/Google.js", diff --git a/lib/OpenLayers/Layer/Image.js b/lib/OpenLayers/Layer/Image.js new file mode 100644 index 0000000000..0986dfd760 --- /dev/null +++ b/lib/OpenLayers/Layer/Image.js @@ -0,0 +1,184 @@ +/** + * @fileoverview Image Layer + * @author Tim Schaub + */ + +/** + * @class + * + * @requires OpenLayers/Layer.js + */ +OpenLayers.Layer.Image = OpenLayers.Class.create(); +OpenLayers.Layer.Image.prototype = + OpenLayers.Class.inherit(OpenLayers.Layer, { + + /** @type String */ + name: null, + + /** @type String */ + url: null, + + /** @type OpenLayers.Bounds */ + extent: null, + + /** @type OpenLayers.Size */ + size: null, + + /** @type Object */ + options: null, + + /** @type OpenLayers.Tile.Image */ + tile: null, + + /** + * The ratio of height/width represented by a single pixel in the graphic + * + * @type Float */ + aspectRatio: null, + + /** + * @constructor + * + * @param {String} name + * @param {String} url Relative or absolute path to the image + * @param {OpenLayers.Bounds} extent The extent represented by the image + * @param {OpenLayers.Size} size The size (in pixels) of the image + * @param {Object} options Hashtable of extra options to tag onto the layer + */ + initialize: function(name, url, extent, size, options) { + this.url = url; + this.extent = extent; + this.size = size; + this.aspectRatio = (this.extent.getHeight() / this.size.h) / + (this.extent.getWidth() / this.size.w); + OpenLayers.Layer.prototype.initialize.apply(this, [name, options]); + + // unless explicitly set in options, the layer will be a base layer + if((options == null) || (options.isBaseLayer == null)) { + this.isBaseLayer = true; + } + }, + + /** + * + */ + destroy: function() { + this.tile.destroy(); + this.tile = null; + OpenLayers.Layer.prototype.destroy.apply(this, arguments); + }, + + /** + * @param {Object} obj + * + * @returns An exact clone of this OpenLayers.Layer.Image + * @type OpenLayers.Layer.Image + */ + clone: function(obj) { + + if(obj == null) { + obj = new OpenLayers.Layer.Image(this.name, + this.url, + this.extent, + this.size, + this.options); + } + + //get all additions from superclasses + obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]); + + // copy/set any non-init, non-simple values here + + return obj; + }, + + /** + * This is a bad method to have here. It would be nicer to be able + * to ask Layer directly. + */ + shouldCalcResolutions: function() { + var props = new Array( + 'scales', 'resolutions', + 'maxScale', 'minScale', + 'maxResolution', 'minResolution', + 'minExtent', 'maxExtent', + 'numZoomLevels', 'maxZoomLevel' + ); + for(var i=0; i < props.length; i++) { + var property = props[i]; + if(this.options[property] != null) { + return false; + } + } + return true; + }, + + + /** + * @param {OpenLayers.Map} map + */ + setMap: function(map) { + // If nothing to do with resolutions has been set, assume a single + // resolution determined by extent/size + if(this.shouldCalcResolutions()) { + this.options.resolutions = [this.extent.getWidth() / this.size.w]; + } + OpenLayers.Layer.prototype.setMap.apply(this, arguments); + }, + + /** When zooming or first rendering, create a new tile for the image. + * + * @param {OpenLayers.Bounds} bounds + * @param {Boolean} zoomChanged + * @param {Boolean} dragging + */ + moveTo:function(bounds, zoomChanged, dragging) { + OpenLayers.Layer.prototype.moveTo.apply(this, arguments); + + var firstRendering = (this.tile == null); + + if(zoomChanged || firstRendering) { + + //clear out the old tile + if(this.tile) { + this.tile.destroy(); + this.tile = null; + } + + //determine new tile bounds + var tileBounds = this.extent.clone(); + + //determine new tile size + var tileWidth = this.extent.getWidth() / this.map.getResolution(); + var tileHeight = this.extent.getHeight() / + (this.map.getResolution() * this.aspectRatio); + var tileSize = new OpenLayers.Size(tileWidth, tileHeight); + + //determine new position (upper left corner of new bounds) + var ul = new OpenLayers.LonLat(tileBounds.left, tileBounds.top); + var pos = this.map.getLayerPxFromLonLat(ul); + + this.tile = new OpenLayers.Tile.Image(this, pos, tileBounds, + this.url, tileSize); + this.tile.draw(); + } + }, + + /** + * @param {String} newUrl + */ + setUrl: function(newUrl) { + this.url = newUrl; + this.moveTo(); + }, + + /** + * @param {OpenLayers.Bounds} bounds + */ + getURL: function(bounds) { + return this.url; + }, + + /** @final @type String */ + CLASS_NAME: "OpenLayers.Layer.Image" +}); diff --git a/tests/list-tests.html b/tests/list-tests.html index 9fb3df2819..74c8dc7852 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -11,6 +11,7 @@
  • test_Events.html
  • test_Util.html
  • test_Layer.html
  • +
  • test_Layer_Image.html
  • test_Layer_EventPane.html
  • test_Layer_FixedZoomLevels.html
  • test_Layer_HTTPRequest.html
  • diff --git a/tests/test_Layer_Image.html b/tests/test_Layer_Image.html new file mode 100644 index 0000000000..207f825d95 --- /dev/null +++ b/tests/test_Layer_Image.html @@ -0,0 +1,96 @@ + + + + + + +
    +
    + +