diff --git a/examples/full-screen.js b/examples/full-screen.js index a02fc63e8b..b5e6b30486 100644 --- a/examples/full-screen.js +++ b/examples/full-screen.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); +goog.require('ol.View2D'); goog.require('ol.source.MapQuestOpenAerial'); @@ -17,8 +18,10 @@ var layer = new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }); var map = new ol.Map({ - center: new ol.Coordinate(0, 0), layers: new ol.Collection([layer]), target: 'map', - zoom: 2 + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 0 + }) }); diff --git a/examples/overlay-and-popup.js b/examples/overlay-and-popup.js index 4b9b9f7222..6e98be100e 100644 --- a/examples/overlay-and-popup.js +++ b/examples/overlay-and-popup.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); +goog.require('ol.View2D'); goog.require('ol.overlay.Overlay'); goog.require('ol.source.MapQuestOpenAerial'); @@ -17,11 +18,14 @@ if (goog.DEBUG) { var layer = new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }); + var map = new ol.Map({ - center: new ol.Coordinate(0, 0), layers: new ol.Collection([layer]), target: 'map', - zoom: 2 + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 2 + }) }); // Vienna label diff --git a/examples/side-by-side.js b/examples/side-by-side.js index d2e9817662..8fffdf17a8 100644 --- a/examples/side-by-side.js +++ b/examples/side-by-side.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.RendererHint'); +goog.require('ol.View2D'); goog.require('ol.control.MousePosition'); goog.require('ol.interaction.Keyboard'); goog.require('ol.layer.TileLayer'); @@ -20,12 +21,16 @@ var layer = new ol.layer.TileLayer({ source: new ol.source.MapQuestOpenAerial() }); -var domMap = new ol.Map({ +var view = new ol.View2D({ center: new ol.Coordinate(0, 0), + zoom: 1 +}); + +var domMap = new ol.Map({ layers: new ol.Collection([layer]), renderer: ol.RendererHint.DOM, target: 'domMap', - zoom: 1 + view: view }); domMap.getControls().push(new ol.control.MousePosition({ @@ -40,10 +45,8 @@ var webglMap = new ol.Map({ target: 'webglMap' }); if (webglMap !== null) { - webglMap.bindTo('center', domMap); webglMap.bindTo('layers', domMap); - webglMap.bindTo('resolution', domMap); - webglMap.bindTo('rotation', domMap); + webglMap.bindTo('view', domMap); } webglMap.getControls().push(new ol.control.MousePosition({ @@ -88,7 +91,7 @@ keyboardInteraction.addCallback('O', function() { layer.setOpacity(layer.getOpacity() + 0.1); }); keyboardInteraction.addCallback('r', function() { - webglMap.setRotation(0); + view.setRotation(0); }); keyboardInteraction.addCallback('s', function() { layer.setSaturation(layer.getSaturation() - 0.1); diff --git a/examples/two-layers.js b/examples/two-layers.js index 53824ff367..9a3a556845 100644 --- a/examples/two-layers.js +++ b/examples/two-layers.js @@ -3,6 +3,7 @@ goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.Projection'); goog.require('ol.RendererHint'); +goog.require('ol.View2D'); goog.require('ol.layer.TileLayer'); goog.require('ol.source.BingMaps'); goog.require('ol.source.TileJSON'); @@ -23,19 +24,19 @@ var layers = new ol.Collection([ ]); var webglMap = new ol.Map({ - center: ol.Projection.transformWithCodes( - new ol.Coordinate(-77.93255, 37.9555), 'EPSG:4326', 'EPSG:3857'), layers: layers, renderer: ol.RendererHint.WEBGL, target: 'webglMap', - zoom: 5 + view: new ol.View2D({ + center: ol.Projection.transformWithCodes( + new ol.Coordinate(-77.93255, 37.9555), 'EPSG:4326', 'EPSG:3857'), + zoom: 5 + }) }); var domMap = new ol.Map({ renderer: ol.RendererHint.DOM, target: 'domMap' }); -domMap.bindTo('center', webglMap); domMap.bindTo('layers', webglMap); -domMap.bindTo('resolution', webglMap); -domMap.bindTo('rotation', webglMap); +domMap.bindTo('view', webglMap); diff --git a/examples/wms-custom-proj.js b/examples/wms-custom-proj.js index a61ac2ebb3..2ab93080fe 100644 --- a/examples/wms-custom-proj.js +++ b/examples/wms-custom-proj.js @@ -5,6 +5,7 @@ goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.Projection'); +goog.require('ol.View2D'); goog.require('ol.source.TiledWMS'); @@ -50,12 +51,14 @@ var layers = new ol.Collection([ ]); var map = new ol.Map({ - center: new ol.Coordinate(660000, 190000), projection: epsg21781, // By setting userProjection to the same as projection, we do not need // proj4js because we do not need any transforms. userProjection: epsg21781, layers: layers, target: 'map', - zoom: 9 + view: new ol.View2D({ + center: new ol.Coordinate(660000, 190000), + zoom: 9 + }) }); diff --git a/examples/wms.js b/examples/wms.js index e475b8ab65..18788dd342 100644 --- a/examples/wms.js +++ b/examples/wms.js @@ -4,6 +4,7 @@ goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); +goog.require('ol.View2D'); goog.require('ol.source.MapQuestOpenAerial'); goog.require('ol.source.TiledWMS'); @@ -31,6 +32,8 @@ var map = new ol.Map({ renderer: ol.RendererHint.DOM, layers: layers, target: 'map', - center: new ol.Coordinate(-10997148, 4569099), - zoom: 4 + view: new ol.View2D({ + center: new ol.Coordinate(-10997148, 4569099), + zoom: 4 + }) }); diff --git a/src/objectliterals.exports b/src/objectliterals.exports index d3f7330bb6..fcda1d5bdb 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -24,7 +24,6 @@ @exportObjectLiteralProperty ol.layer.LayerOptions.visible boolean|undefined @exportObjectLiteral ol.MapOptions -@exportObjectLiteralProperty ol.MapOptions.center ol.Coordinate|undefined @exportObjectLiteralProperty ol.MapOptions.controls ol.Collection|undefined @exportObjectLiteralProperty ol.MapOptions.doubleClickZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.dragPan boolean|undefined @@ -32,22 +31,14 @@ @exportObjectLiteralProperty ol.MapOptions.keyboard boolean|undefined @exportObjectLiteralProperty ol.MapOptions.keyboardPanOffset number|undefined @exportObjectLiteralProperty ol.MapOptions.layers ol.Collection|undefined -@exportObjectLiteralProperty ol.MapOptions.maxResolution number|undefined @exportObjectLiteralProperty ol.MapOptions.mouseWheelZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.mouseWheelZoomDelta number|undefined -@exportObjectLiteralProperty ol.MapOptions.numZoomLevels number|undefined -@exportObjectLiteralProperty ol.MapOptions.projection ol.Projection|string|undefined @exportObjectLiteralProperty ol.MapOptions.renderer ol.RendererHint|undefined @exportObjectLiteralProperty ol.MapOptions.renderers Array.|undefined -@exportObjectLiteralProperty ol.MapOptions.resolution number|undefined -@exportObjectLiteralProperty ol.MapOptions.resolutions Array.|undefined -@exportObjectLiteralProperty ol.MapOptions.rotate boolean|undefined @exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.target Element|string -@exportObjectLiteralProperty ol.MapOptions.userProjection ol.Projection|string|undefined -@exportObjectLiteralProperty ol.MapOptions.zoom number|undefined +@exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined @exportObjectLiteralProperty ol.MapOptions.zoomDelta number|undefined -@exportObjectLiteralProperty ol.MapOptions.zoomFactor number|undefined @exportObjectLiteral ol.overlay.OverlayOptions @exportObjectLiteralProperty ol.overlay.OverlayOptions.coordinate ol.Coordinate|undefined @@ -71,3 +62,14 @@ @exportObjectLiteralProperty ol.source.TiledWMSOptions.projection ol.Projection|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.url string|undefined @exportObjectLiteralProperty ol.source.TiledWMSOptions.urls Array.|undefined + +@exportObjectLiteral ol.View2DOptions +@exportObjectLiteralProperty ol.View2DOptions.center ol.Coordinate|undefined +@exportObjectLiteralProperty ol.View2DOptions.maxResolution number|undefined +@exportObjectLiteralProperty ol.View2DOptions.numZoomLevels number|undefined +@exportObjectLiteralProperty ol.View2DOptions.projection ol.Projection|string|undefined +@exportObjectLiteralProperty ol.View2DOptions.resolution number|undefined +@exportObjectLiteralProperty ol.View2DOptions.resolutions Array.|undefined +@exportObjectLiteralProperty ol.View2DOptions.rotation number|undefined +@exportObjectLiteralProperty ol.View2DOptions.zoom number|undefined +@exportObjectLiteralProperty ol.View2DOptions.zoomFactor number|undefined diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js index 36f3391434..27f5a7f836 100644 --- a/src/ol/control/attributioncontrol.js +++ b/src/ol/control/attributioncontrol.js @@ -2,6 +2,7 @@ // FIXME handle date line wrap // FIXME handle layer order // FIXME check clean-up code +// FIXME works for View2D only goog.provide('ol.control.Attribution'); @@ -14,6 +15,8 @@ goog.require('goog.style'); goog.require('ol.Collection'); goog.require('ol.CoverageArea'); goog.require('ol.TileCoverageArea'); +goog.require('ol.View2D'); +goog.require('ol.View2DProperty'); goog.require('ol.control.Control'); goog.require('ol.layer.Layer'); @@ -33,12 +36,6 @@ ol.control.Attribution = function(attributionOptions) { 'class': 'ol-attribution' }, this.ulElement_); - /** - * @private - * @type {Array.} - */ - this.layersListenerKeys_ = null; - /** * @private * @type {Object.} @@ -63,6 +60,18 @@ ol.control.Attribution = function(attributionOptions) { */ this.mapListenerKeys_ = null; + /** + * @private + * @type {Array.} + */ + this.layersListenerKeys_ = null; + + /** + * @private + * @type {Array.} + */ + this.viewListenerKeys_ = null; + goog.base(this, { element: element, map: attributionOptions.map, @@ -110,14 +119,17 @@ ol.control.Attribution.prototype.createAttributionElementsForLayer_ = var map = this.getMap(); var mapIsDef = map.isDef(); - var mapExtent = /** @type {ol.Extent} */ map.getExtent(); - var mapProjection = /** @type {ol.Projection} */ map.getProjection(); - var mapResolution = /** @type {number} */ map.getResolution(); - var layerVisible = layer.getVisible(); var attributionVisibilities; if (mapIsDef && layerVisible) { + var mapSize = /** @type {ol.Size} */ (map.getSize()); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var mapExtent = view.getExtent(mapSize); + var mapProjection = /** @type {ol.Projection} */ (view.getProjection()); + var mapResolution = /** @type {number} */ (view.getResolution()); attributionVisibilities = this.getLayerAttributionVisiblities_( layer, mapExtent, mapResolution, mapProjection); } else { @@ -131,7 +143,7 @@ ol.control.Attribution.prototype.createAttributionElementsForLayer_ = var attributionElement = goog.dom.createElement(goog.dom.TagName.LI); attributionElement.innerHTML = attribution.getHtml(); - if (!map.isDef || + if (!mapIsDef || !layerVisible || goog.isNull(attributionVisibilities) || !attributionVisibilities[attributionKey]) { @@ -151,8 +163,8 @@ ol.control.Attribution.prototype.createAttributionElementsForLayer_ = /** * @param {ol.layer.Layer} layer Layer. - * @param {ol.Extent} mapExtent Map extent. - * @param {number} mapResolution Map resolution. + * @param {ol.Extent} mapExtent View extent. + * @param {number} mapResolution View resolution. * @param {ol.Projection} mapProjection Map projection. * @return {Object.} Attribution visibilities. * @private @@ -240,17 +252,8 @@ ol.control.Attribution.prototype.handleLayerLoad = function(event) { * @protected */ ol.control.Attribution.prototype.handleLayerVisibleChanged = function(event) { - - var map = this.getMap(); - var mapIsDef = map.isDef(); - var mapExtent = /** @type {ol.Extent} */ map.getExtent(); - var mapProjection = /** @type {ol.Projection} */ map.getProjection(); - var mapResolution = /** @type {number} */ map.getResolution(); - var layer = /** @type {ol.layer.Layer} */ (event.target); - - this.updateLayerAttributionsVisibility_( - layer, mapIsDef, mapExtent, mapResolution, mapProjection); + this.updateLayerAttributionsVisibility_(layer); }; @@ -279,20 +282,26 @@ ol.control.Attribution.prototype.handleLayersRemove = /** * @protected */ -ol.control.Attribution.prototype.handleMapChanged = function() { - +ol.control.Attribution.prototype.handleMapViewChanged = function() { + if (!goog.isNull(this.viewListenerKeys_)) { + goog.array.forEach(this.viewListenerKeys_, goog.events.unlistenByKey); + this.viewListenerKeys_ = null; + } var map = this.getMap(); - var mapIsDef = map.isDef(); - var mapExtent = /** @type {ol.Extent} */ map.getExtent(); - var mapProjection = /** @type {ol.Projection} */ map.getProjection(); - var mapResolution = map.getResolution(); - - var layers = map.getLayers(); - layers.forEach(function(layer) { - this.updateLayerAttributionsVisibility_( - layer, mapIsDef, mapExtent, mapResolution, mapProjection); - }, this); - + goog.asserts.assert(!goog.isNull(map)); + var view = map.getView(); + if (!goog.isNull(view)) { + // FIXME works for View2D only + goog.asserts.assert(view instanceof ol.View2D); + this.viewListenerKeys_ = [ + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.CENTER), + this.updateAttributions, false, this), + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.RESOLUTION), + this.updateAttributions, false, this) + ]; + } }; @@ -359,35 +368,51 @@ ol.control.Attribution.prototype.setMap = function(map) { goog.base(this, 'setMap', map); if (!goog.isNull(map)) { this.mapListenerKeys_ = [ - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.CENTER), - this.handleMapChanged, false, this), goog.events.listen( map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), this.handleMapLayersChanged, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION), - this.handleMapChanged, false, this), goog.events.listen( map, ol.Object.getChangedEventType(ol.MapProperty.SIZE), - this.handleMapChanged, false, this) + this.updateAttributions, false, this), + goog.events.listen( + map, ol.Object.getChangedEventType(ol.MapProperty.VIEW), + this.updateAttributions, false, this) ]; + this.handleMapViewChanged(); this.handleMapLayersChanged(); } }; +/** + * @protected + */ +ol.control.Attribution.prototype.updateAttributions = function() { + + var map = this.getMap(); + var layers = map.getLayers(); + layers.forEach(function(layer) { + this.updateLayerAttributionsVisibility_(layer); + }, this); + +}; + + /** * @param {ol.layer.Layer} layer Layer. - * @param {boolean} mapIsDef Map is defined. - * @param {ol.Extent} mapExtent Map extent. - * @param {number} mapResolution Map resolution. - * @param {ol.Projection} mapProjection Map projection. * @private */ ol.control.Attribution.prototype.updateLayerAttributionsVisibility_ = - function(layer, mapIsDef, mapExtent, mapResolution, mapProjection) { - if (mapIsDef && layer.getVisible()) { + function(layer) { + var map = this.getMap(); + if (map.isDef() && layer.getVisible()) { + var mapSize = /** @type {ol.Size} */ (map.getSize()); + var view = map.getView(); + // FIXME works for View2D only + goog.asserts.assert(view instanceof ol.View2D); + var mapExtent = view.getExtent(mapSize); + var mapProjection = /** @type {ol.Projection} */ (view.getProjection()); + var mapResolution = /** @type {number} */ (view.getResolution()); var attributionVisibilities = this.getLayerAttributionVisiblities_( layer, mapExtent, mapResolution, mapProjection); goog.object.forEach( diff --git a/src/ol/control/mousepositioncontrol.js b/src/ol/control/mousepositioncontrol.js index 6466e73f36..653baac95d 100644 --- a/src/ol/control/mousepositioncontrol.js +++ b/src/ol/control/mousepositioncontrol.js @@ -1,4 +1,5 @@ // FIXME should listen on appropriate pane, once it is defined +// FIXME works for View2D only goog.provide('ol.control.MousePosition'); @@ -60,21 +61,40 @@ ol.control.MousePosition = function(mousePositionOptions) { * @private * @type {Array.} */ - this.listenerKeys_ = []; + this.mapListenerKeys_ = null; - this.handleMapProjectionChanged(); + /** + * @private + * @type {Array.} + */ + this.viewListenerKeys_ = null; + this.handleViewProjectionChanged_(); }; goog.inherits(ol.control.MousePosition, ol.control.Control); /** - * @protected + * @private */ -ol.control.MousePosition.prototype.handleMapProjectionChanged = function() { - this.updateTransform_(); - // FIXME should we instead re-calculate using the last known mouse position? - this.element.innerHTML = this.undefinedHtml_; +ol.control.MousePosition.prototype.handleMapViewChanged_ = function() { + var map = this.getMap(); + goog.asserts.assert(!goog.isNull(map)); + if (!goog.isNull(this.viewListenerKeys_)) { + goog.array.forEach(this.viewListenerKeys_, goog.events.unlistenByKey); + this.viewListenerKeys_ = null; + } + var view = map.getView(); + if (goog.isDefAndNotNull(view)) { + // FIXME works for View2D only + goog.asserts.assert(view instanceof ol.View2D); + this.viewListenerKeys_ = [ + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.ROTATION), + this.handleViewProjectionChanged_, false, this) + ]; + this.handleViewProjectionChanged_(); + } }; @@ -112,25 +132,36 @@ ol.control.MousePosition.prototype.handleMouseOut = function(browserEvent) { }; +/** + * @private + */ +ol.control.MousePosition.prototype.handleViewProjectionChanged_ = function() { + this.updateTransform_(); + // FIXME should we instead re-calculate using the last known + // mouse position? + this.element.innerHTML = this.undefinedHtml_; +}; + + /** * @inheritDoc */ ol.control.MousePosition.prototype.setMap = function(map) { - if (!goog.isNull(this.listenerKeys_)) { - goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); - this.listenerKeys_ = null; + if (!goog.isNull(this.mapListenerKeys_)) { + goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey); + this.mapListenerKeys_ = null; } goog.base(this, 'setMap', map); if (!goog.isNull(map)) { var viewport = map.getViewport(); this.listenerKeys = [ - goog.events.listen(map, - ol.Object.getChangedEventType(ol.MapProperty.PROJECTION), - this.handleMapProjectionChanged, false, this), goog.events.listen(viewport, goog.events.EventType.MOUSEMOVE, this.handleMouseMove, false, this), goog.events.listen(viewport, goog.events.EventType.MOUSEOUT, - this.handleMouseOut, false, this) + this.handleMouseOut, false, this), + goog.events.listen(map, + ol.Object.getChangedEventType(ol.MapProperty.VIEW), + this.handleMapViewChanged_, false, this) ]; this.updateTransform_(); } @@ -141,16 +172,19 @@ ol.control.MousePosition.prototype.setMap = function(map) { * @private */ ol.control.MousePosition.prototype.updateTransform_ = function() { - var map = this.getMap(); - if (goog.isNull(map)) { - this.transform_ = ol.Projection.identityTransform; - } else { - var mapProjection = map.getProjection(); - if (!goog.isDef(mapProjection) || !goog.isDef(this.projection_)) { + var map, view; + if (!goog.isNull(map = this.getMap()) && + !goog.isNull(view = map.getView())) { + // FIXME works for View2D only + goog.asserts.assert(view instanceof ol.View2D); + var viewProjection = view.getProjection(); + if (!goog.isDef(viewProjection) || !goog.isDef(this.projection_)) { this.transform_ = ol.Projection.identityTransform; } else { this.transform_ = - ol.Projection.getTransform(mapProjection, this.projection_); + ol.Projection.getTransform(viewProjection, this.projection_); } + } else { + this.transform_ = ol.Projection.identityTransform; } }; diff --git a/src/ol/control/zoomcontrol.js b/src/ol/control/zoomcontrol.js index b429252ba0..82be362311 100644 --- a/src/ol/control/zoomcontrol.js +++ b/src/ol/control/zoomcontrol.js @@ -1,3 +1,5 @@ +// FIXME works for View2D only + goog.provide('ol.control.Zoom'); goog.require('goog.dom'); @@ -58,7 +60,9 @@ goog.inherits(ol.control.Zoom, ol.control.Control); ol.control.Zoom.prototype.handleIn_ = function(browserEvent) { // prevent #zoomIn anchor from getting appended to the url browserEvent.preventDefault(); - this.getMap().zoom(this.delta_); + var map = this.getMap(); + // FIXME works for View2D only + map.getView().zoom(map, this.delta_); }; @@ -69,5 +73,7 @@ ol.control.Zoom.prototype.handleIn_ = function(browserEvent) { ol.control.Zoom.prototype.handleOut_ = function(browserEvent) { // prevent #zoomOut anchor from getting appended to the url browserEvent.preventDefault(); - this.getMap().zoom(-this.delta_); + var map = this.getMap(); + // FIXME works for View2D only + map.getView().zoom(map, -this.delta_); }; diff --git a/src/ol/interaction/dblclickzoominteraction.js b/src/ol/interaction/dblclickzoominteraction.js index c6e52fb1bc..b5e3e1e589 100644 --- a/src/ol/interaction/dblclickzoominteraction.js +++ b/src/ol/interaction/dblclickzoominteraction.js @@ -1,7 +1,10 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.DblClickZoom'); goog.require('ol.MapBrowserEvent'); goog.require('ol.MapBrowserEvent.EventType'); +goog.require('ol.View2D'); goog.require('ol.interaction.Interaction'); @@ -35,7 +38,10 @@ ol.interaction.DblClickZoom.prototype.handleMapBrowserEvent = var anchor = mapBrowserEvent.getCoordinate(); var delta = mapBrowserEvent.browserEvent.shiftKey ? -this.delta_ : this.delta_; - map.zoom(delta, anchor); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + view.zoom(map, delta, anchor); mapBrowserEvent.preventDefault(); browserEvent.preventDefault(); } diff --git a/src/ol/interaction/draginteraction.js b/src/ol/interaction/draginteraction.js index 952b4ef1ef..b41e548a6b 100644 --- a/src/ol/interaction/draginteraction.js +++ b/src/ol/interaction/draginteraction.js @@ -89,6 +89,7 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent = if (!map.isDef()) { return; } + var view = map.getView(); var browserEvent = mapBrowserEvent.browserEvent; if (this.dragging_) { if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) { @@ -109,7 +110,7 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent = this.startY = browserEvent.clientY; this.deltaX = 0; this.deltaY = 0; - this.startCenter = /** @type {!ol.Coordinate} */ map.getCenter(); + this.startCenter = /** @type {!ol.Coordinate} */ (view.getCenter()); this.startCoordinate = /** @type {ol.Coordinate} */ (mapBrowserEvent.getCoordinate()); var handled = this.handleDragStart(mapBrowserEvent); diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index d3a2c2fa7d..32a5acc697 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -1,7 +1,11 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.DragPan'); +goog.require('goog.asserts'); goog.require('ol.Coordinate'); goog.require('ol.MapBrowserEvent'); +goog.require('ol.View2D'); goog.require('ol.interaction.ConditionType'); goog.require('ol.interaction.Drag'); @@ -31,8 +35,11 @@ goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); */ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { var map = mapBrowserEvent.map; - var resolution = map.getResolution(); - var rotation = map.getRotation(); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var resolution = view.getResolution(); + var rotation = view.getRotation(); var delta = new ol.Coordinate(-resolution * this.deltaX, resolution * this.deltaY); if (map.canRotate() && goog.isDef(rotation)) { @@ -41,7 +48,7 @@ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { var newCenter = new ol.Coordinate( this.startCenter.x + delta.x, this.startCenter.y + delta.y); map.requestRenderFrame(); - map.setCenter(newCenter); + view.setCenter(newCenter); }; diff --git a/src/ol/interaction/dragrotateandzoominteraction.js b/src/ol/interaction/dragrotateandzoominteraction.js index 0fa9992f65..0615f25b56 100644 --- a/src/ol/interaction/dragrotateandzoominteraction.js +++ b/src/ol/interaction/dragrotateandzoominteraction.js @@ -1,7 +1,10 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.DragRotateAndZoom'); goog.require('goog.math.Vec2'); goog.require('ol.MapBrowserEvent'); +goog.require('ol.View2D'); goog.require('ol.interaction.ConditionType'); goog.require('ol.interaction.Drag'); @@ -50,12 +53,15 @@ ol.interaction.DragRotateAndZoom.prototype.handleDrag = browserEvent.offsetX - size.width / 2, size.height / 2 - browserEvent.offsetY); var theta = Math.atan2(delta.y, delta.x); + var resolution = this.startRatio_ * delta.magnitude(); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); map.requestRenderFrame(); // FIXME the calls to map.rotate and map.zoomToResolution should use // map.withFrozenRendering but an assertion fails :-( - map.rotate(this.startRotation_, -theta); - var resolution = this.startRatio_ * delta.magnitude(); - map.zoomToResolution(resolution); + view.rotate(map, this.startRotation_, -theta); + view.zoomToResolution(map, resolution); }; @@ -66,14 +72,15 @@ ol.interaction.DragRotateAndZoom.prototype.handleDragStart = function(mapBrowserEvent) { var browserEvent = mapBrowserEvent.browserEvent; var map = mapBrowserEvent.map; + var view = map.getView().getView2D(); if (map.canRotate() && this.condition_(browserEvent)) { - var resolution = map.getResolution(); + var resolution = view.getResolution(); var size = map.getSize(); var delta = new goog.math.Vec2( browserEvent.offsetX - size.width / 2, size.height / 2 - browserEvent.offsetY); var theta = Math.atan2(delta.y, delta.x); - this.startRotation_ = (map.getRotation() || 0) + theta; + this.startRotation_ = (view.getRotation() || 0) + theta; this.startRatio_ = resolution / delta.magnitude(); map.requestRenderFrame(); return true; diff --git a/src/ol/interaction/dragrotateinteraction.js b/src/ol/interaction/dragrotateinteraction.js index d574a72a64..f1aef8630e 100644 --- a/src/ol/interaction/dragrotateinteraction.js +++ b/src/ol/interaction/dragrotateinteraction.js @@ -1,6 +1,7 @@ goog.provide('ol.interaction.DragRotate'); goog.require('ol.MapBrowserEvent'); +goog.require('ol.View2D'); goog.require('ol.interaction.ConditionType'); goog.require('ol.interaction.Drag'); @@ -42,8 +43,11 @@ ol.interaction.DragRotate.prototype.handleDrag = function(mapBrowserEvent) { var theta = Math.atan2( size.height / 2 - offset.y, offset.x - size.width / 2); + // FIXME supports View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); map.requestRenderFrame(); - map.rotate(this.startRotation_, -theta); + view.rotate(map, this.startRotation_, -theta); }; @@ -54,6 +58,9 @@ ol.interaction.DragRotate.prototype.handleDragStart = function(mapBrowserEvent) { var browserEvent = mapBrowserEvent.browserEvent; var map = mapBrowserEvent.map; + // FIXME supports View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); if (browserEvent.isMouseActionButton() && this.condition_(browserEvent) && map.canRotate()) { map.requestRenderFrame(); @@ -62,7 +69,7 @@ ol.interaction.DragRotate.prototype.handleDragStart = var theta = Math.atan2( size.height / 2 - offset.y, offset.x - size.width / 2); - this.startRotation_ = (map.getRotation() || 0) + theta; + this.startRotation_ = (view.getRotation() || 0) + theta; return true; } else { return false; diff --git a/src/ol/interaction/dragzoominteraction.js b/src/ol/interaction/dragzoominteraction.js index 367b80000f..22d94334eb 100644 --- a/src/ol/interaction/dragzoominteraction.js +++ b/src/ol/interaction/dragzoominteraction.js @@ -1,4 +1,5 @@ // FIXME draw drag box +// FIXME works for View2D only goog.provide('ol.interaction.DragZoom'); @@ -63,7 +64,19 @@ ol.interaction.DragZoom.prototype.handleDragEnd = var extent = ol.Extent.boundingExtent( this.startCoordinate, mapBrowserEvent.getCoordinate()); - map.fitExtent(extent); + map.withFrozenRendering(function() { + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var mapSize = /** @type {ol.Size} */ (map.getSize()); + view.fitExtent(extent, mapSize); + if (map.canRotate()) { + // FIXME we don't set the rotation if the map doesn't + // support rotation, this will prevent any map using + // that view from rotating, which may not be desired + view.setRotation(0); + } + }); } }; diff --git a/src/ol/interaction/keyboardpaninteraction.js b/src/ol/interaction/keyboardpaninteraction.js index c663ddbcd8..384b7d9d4c 100644 --- a/src/ol/interaction/keyboardpaninteraction.js +++ b/src/ol/interaction/keyboardpaninteraction.js @@ -1,7 +1,10 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.KeyboardPan'); goog.require('goog.events.KeyCodes'); goog.require('goog.events.KeyHandler.EventType'); +goog.require('ol.View2D'); goog.require('ol.interaction.Interaction'); @@ -39,7 +42,10 @@ ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = keyCode == goog.events.KeyCodes.RIGHT || keyCode == goog.events.KeyCodes.UP) { var map = mapBrowserEvent.map; - var resolution = map.getResolution(); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + var resolution = view.getResolution(); var delta; var mapUnitsDelta = resolution * this.pixelDelta_; if (keyCode == goog.events.KeyCodes.DOWN) { @@ -52,10 +58,10 @@ ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = goog.asserts.assert(keyCode == goog.events.KeyCodes.UP); delta = new ol.Coordinate(0, mapUnitsDelta); } - var oldCenter = map.getCenter(); + var oldCenter = view.getCenter(); var newCenter = new ol.Coordinate( oldCenter.x + delta.x, oldCenter.y + delta.y); - map.setCenter(newCenter); + view.setCenter(newCenter); keyEvent.preventDefault(); mapBrowserEvent.preventDefault(); } diff --git a/src/ol/interaction/keyboardzoominteraction.js b/src/ol/interaction/keyboardzoominteraction.js index c086435979..3075754ca7 100644 --- a/src/ol/interaction/keyboardzoominteraction.js +++ b/src/ol/interaction/keyboardzoominteraction.js @@ -1,7 +1,10 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.KeyboardZoom'); goog.require('goog.events.KeyCodes'); goog.require('goog.events.KeyHandler.EventType'); +goog.require('ol.View2D'); goog.require('ol.interaction.Interaction'); @@ -28,7 +31,10 @@ ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = if (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0)) { var map = mapBrowserEvent.map; var delta = (charCode == '+'.charCodeAt(0)) ? 4 : -4; - map.zoom(delta); + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + view.zoom(map, delta); keyEvent.preventDefault(); mapBrowserEvent.preventDefault(); } diff --git a/src/ol/interaction/mousewheelzoominteraction.js b/src/ol/interaction/mousewheelzoominteraction.js index 563c4dbd8a..7e3c1769ac 100644 --- a/src/ol/interaction/mousewheelzoominteraction.js +++ b/src/ol/interaction/mousewheelzoominteraction.js @@ -1,8 +1,11 @@ +// FIXME works for View2D only + goog.provide('ol.interaction.MouseWheelZoom'); goog.require('goog.events.MouseWheelEvent'); goog.require('goog.events.MouseWheelHandler.EventType'); goog.require('ol.MapBrowserEvent'); +goog.require('ol.View2D'); @@ -36,8 +39,11 @@ ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent = goog.asserts.assert(mouseWheelEvent instanceof goog.events.MouseWheelEvent); var anchor = mapBrowserEvent.getCoordinate(); var delta = mouseWheelEvent.deltaY < 0 ? this.delta_ : -this.delta_; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); map.requestRenderFrame(); - map.zoom(delta, anchor); + view.zoom(map, delta, anchor); mapBrowserEvent.preventDefault(); mouseWheelEvent.preventDefault(); } diff --git a/src/ol/iview.js b/src/ol/iview.js new file mode 100644 index 0000000000..5b7663bd1d --- /dev/null +++ b/src/ol/iview.js @@ -0,0 +1,27 @@ +goog.provide('ol.IView'); + +goog.require('ol.IView2D'); +goog.require('ol.IView3D'); + + + +/** + * Interface for views. + * @interface + */ +ol.IView = function() { +}; + + +/** + * @return {ol.IView2D} View2D. + */ +ol.IView.prototype.getView2D = function() { +}; + + +/** + * @return {ol.IView3D} View3D. + */ +ol.IView.prototype.getView3D = function() { +}; diff --git a/src/ol/iview2d.js b/src/ol/iview2d.js new file mode 100644 index 0000000000..d8840a8cba --- /dev/null +++ b/src/ol/iview2d.js @@ -0,0 +1,38 @@ +goog.provide('ol.IView2D'); + + + +/** + * Interface for views. + * @interface + */ +ol.IView2D = function() { +}; + + +/** + * @return {ol.Coordinate|undefined} Map center. + */ +ol.IView2D.prototype.getCenter = function() { +}; + + +/** + * @return {ol.Projection|undefined} Map projection. + */ +ol.IView2D.prototype.getProjection = function() { +}; + + +/** + * @return {number|undefined} Map resolution. + */ +ol.IView2D.prototype.getResolution = function() { +}; + + +/** + * @return {number|undefined} Map rotation. + */ +ol.IView2D.prototype.getRotation = function() { +}; diff --git a/src/ol/iview3d.js b/src/ol/iview3d.js new file mode 100644 index 0000000000..90153214b5 --- /dev/null +++ b/src/ol/iview3d.js @@ -0,0 +1,12 @@ +goog.provide('ol.IView3D'); + + + +/** + * Interface for views. + * @interface + */ +ol.IView3D = function() { +}; + + diff --git a/src/ol/map.js b/src/ol/map.js index d7122fa839..8cf12961f6 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -27,17 +27,17 @@ goog.require('goog.object'); goog.require('ol.BrowserFeature'); goog.require('ol.Collection'); goog.require('ol.Color'); -goog.require('ol.Constraints'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.MapBrowserEvent'); goog.require('ol.Object'); goog.require('ol.Pixel'); -goog.require('ol.Projection'); goog.require('ol.ResolutionConstraint'); goog.require('ol.RotationConstraint'); goog.require('ol.Size'); goog.require('ol.TransformFunction'); +goog.require('ol.View'); +goog.require('ol.View2D'); goog.require('ol.control.Attribution'); goog.require('ol.control.Zoom'); goog.require('ol.interaction.DblClickZoom'); @@ -100,13 +100,9 @@ ol.MapEventType = { */ ol.MapProperty = { BACKGROUND_COLOR: 'backgroundColor', - CENTER: 'center', LAYERS: 'layers', - PROJECTION: 'projection', - RESOLUTION: 'resolution', - ROTATION: 'rotation', SIZE: 'size', - USER_PROJECTION: 'userProjection' + VIEW: 'view' }; @@ -130,18 +126,6 @@ ol.Map = function(mapOptions) { var mapOptionsInternal = ol.Map.createOptionsInternal(mapOptions); - /** - * @type {ol.TransformFunction} - * @private - */ - this.userToMapTransform_ = ol.Projection.identityTransform; - - /** - * @type {ol.TransformFunction} - * @private - */ - this.mapToUserTransform_ = ol.Projection.cloneTransform; - /** * @private * @type {goog.async.AnimationDelay} @@ -168,12 +152,6 @@ ol.Map = function(mapOptions) { */ this.target_ = mapOptionsInternal.target; - /** - * @private - * @type {ol.Constraints} - */ - this.constraints_ = mapOptionsInternal.constraints; - /** * @private * @type {Element} @@ -253,14 +231,6 @@ ol.Map = function(mapOptions) { goog.events.listen(this.viewportSizeMonitor_, goog.events.EventType.RESIZE, this.handleBrowserWindowResize, false, this); - goog.events.listen( - this, ol.Object.getChangedEventType(ol.MapProperty.PROJECTION), - this.handleProjectionChanged, false, this); - - goog.events.listen( - this, ol.Object.getChangedEventType(ol.MapProperty.USER_PROJECTION), - this.handleUserProjectionChanged, false, this); - this.setValues(mapOptionsInternal.values); this.handleBrowserWindowResize(); @@ -295,30 +265,6 @@ ol.Map.prototype.disposeInternal = function() { }; -/** - * @param {ol.Extent} extent Extent. - */ -ol.Map.prototype.fitExtent = function(extent) { - this.withFrozenRendering(function() { - this.setCenter(extent.getCenter()); - var resolution = this.getResolutionForExtent(extent); - resolution = this.constraints_.resolution(resolution, 0); - this.setResolution(resolution); - if (this.canRotate()) { - this.setRotation(0); - } - }, this); -}; - - -/** - * @param {ol.Extent} userExtent Extent in user projection. - */ -ol.Map.prototype.fitUserExtent = function(userExtent) { - this.fitExtent(userExtent.transform(this.userToMapTransform_)); -}; - - /** * Freeze rendering. */ @@ -340,18 +286,6 @@ goog.exportProperty( ol.Map.prototype.getBackgroundColor); -/** - * @return {ol.Coordinate|undefined} Center. - */ -ol.Map.prototype.getCenter = function() { - return /** @type {ol.Coordinate} */ this.get(ol.MapProperty.CENTER); -}; -goog.exportProperty( - ol.Map.prototype, - 'getCenter', - ol.Map.prototype.getCenter); - - /** * @return {Element} Container. */ @@ -377,25 +311,6 @@ ol.Map.prototype.getCoordinateFromPixel = function(pixel) { }; -/** - * @return {ol.Extent|undefined} Extent. - */ -ol.Map.prototype.getExtent = function() { - if (this.isDef()) { - var center = this.getCenter(); - var resolution = this.getResolution(); - var size = this.getSize(); - var minX = center.x - resolution * size.width / 2; - var minY = center.y - resolution * size.height / 2; - var maxX = center.x + resolution * size.width / 2; - var maxY = center.y + resolution * size.height / 2; - return new ol.Extent(minX, minY, maxX, maxY); - } else { - return undefined; - } -}; - - /** * @return {ol.Collection} Interactions. */ @@ -425,88 +340,11 @@ ol.Map.prototype.getPixelFromCoordinate = function(coordinate) { }; -/** - * @return {ol.Projection|undefined} Projection. - */ -ol.Map.prototype.getProjection = function() { - return /** @type {ol.Projection} */ (this.get(ol.MapProperty.PROJECTION)); -}; -goog.exportProperty( - ol.Map.prototype, - 'getProjection', - ol.Map.prototype.getProjection); - - -/** - * @return {number|undefined} Resolution. - */ -ol.Map.prototype.getResolution = function() { - return /** @type {number} */ this.get(ol.MapProperty.RESOLUTION); -}; -goog.exportProperty( - ol.Map.prototype, - 'getResolution', - ol.Map.prototype.getResolution); - - -/** - * @param {ol.Extent} extent Extent. - * @return {number|undefined} Resolution. - */ -ol.Map.prototype.getResolutionForExtent = function(extent) { - var size = this.getSize(); - if (goog.isDef(size)) { - var xResolution = (extent.maxX - extent.minX) / size.width; - var yResolution = (extent.maxY - extent.minY) / size.height; - return Math.max(xResolution, yResolution); - } else { - return undefined; - } -}; - - -/** - * @return {ol.Extent} Rotated extent. - */ -ol.Map.prototype.getRotatedExtent = function() { - goog.asserts.assert(this.isDef()); - var center = /** @type {!ol.Coordinate} */ this.getCenter(); - var resolution = this.getResolution(); - var rotation = this.getRotation() || 0; - var size = this.getSize(); - var xScale = resolution * size.width / 2; - var yScale = resolution * size.height / 2; - var corners = [ - new ol.Coordinate(-xScale, -yScale), - new ol.Coordinate(-xScale, yScale), - new ol.Coordinate(xScale, -yScale), - new ol.Coordinate(xScale, yScale) - ]; - goog.array.forEach(corners, function(corner) { - corner.rotate(rotation); - corner.add(center); - }); - return ol.Extent.boundingExtent.apply(null, corners); -}; - - -/** - * @return {number} Rotation. - */ -ol.Map.prototype.getRotation = function() { - return /** @type {number} */ this.get(ol.MapProperty.ROTATION) || 0; -}; -goog.exportProperty( - ol.Map.prototype, - 'getRotation', - ol.Map.prototype.getRotation); - - /** * @return {ol.Size|undefined} Size. */ ol.Map.prototype.getSize = function() { - return /** @type {ol.Size|undefined} */ this.get(ol.MapProperty.SIZE); + return /** @type {ol.Size|undefined} */ (this.get(ol.MapProperty.SIZE)); }; goog.exportProperty( ol.Map.prototype, @@ -515,42 +353,15 @@ goog.exportProperty( /** - * @return {ol.Coordinate|undefined} Center in user projection. + * @return {ol.View} View. */ -ol.Map.prototype.getUserCenter = function() { - var center = this.getCenter(); - if (goog.isDef(center)) { - return this.mapToUserTransform_(center); - } else { - return undefined; - } -}; - - -/** - * @return {ol.Extent|undefined} Extent in user projection. - */ -ol.Map.prototype.getUserExtent = function() { - var extent = this.getExtent(); - if (goog.isDef(extent)) { - return extent.transform(this.mapToUserTransform_); - } else { - return undefined; - } -}; - - -/** - * @return {ol.Projection|undefined} Projection. - */ -ol.Map.prototype.getUserProjection = function() { - return /** @type {ol.Projection} */ this.get( - ol.MapProperty.USER_PROJECTION); +ol.Map.prototype.getView = function() { + return /** @type {ol.View} */ (this.get(ol.MapProperty.VIEW)); }; goog.exportProperty( ol.Map.prototype, - 'getUserProjection', - ol.Map.prototype.getUserProjection); + 'getView', + ol.Map.prototype.getView); /** @@ -621,22 +432,6 @@ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { }; -/** - * @protected - */ -ol.Map.prototype.handleProjectionChanged = function() { - this.recalculateTransforms_(); -}; - - -/** - * @protected - */ -ol.Map.prototype.handleUserProjectionChanged = function() { - this.recalculateTransforms_(); -}; - - /** * @protected */ @@ -650,31 +445,12 @@ ol.Map.prototype.handleBrowserWindowResize = function() { * @return {boolean} Is defined. */ ol.Map.prototype.isDef = function() { - return goog.isDefAndNotNull(this.getCenter()) && - goog.isDef(this.getResolution()) && + var view = this.getView(); + return goog.isDef(view) && view.isDef() && goog.isDefAndNotNull(this.getSize()); }; -/** - * @private - */ -ol.Map.prototype.recalculateTransforms_ = function() { - var projection = this.getProjection(); - var userProjection = this.getUserProjection(); - if (goog.isDefAndNotNull(projection) && - goog.isDefAndNotNull(userProjection)) { - this.mapToUserTransform_ = ol.Projection.getTransform( - projection, userProjection); - this.userToMapTransform_ = ol.Projection.getTransform( - userProjection, projection); - } else { - this.mapToUserTransform_ = ol.Projection.cloneTransform; - this.userToMapTransform_ = ol.Projection.identityTransform; - } -}; - - /** * Render. */ @@ -723,16 +499,6 @@ ol.Map.prototype.renderFrame_ = function(time) { }; -/** - * @param {number|undefined} rotation Rotation. - * @param {number} delta Delta. - */ -ol.Map.prototype.rotate = function(rotation, delta) { - rotation = this.constraints_.rotation(rotation, delta); - this.setRotation(rotation); -}; - - /** * @param {ol.Color} backgroundColor Background color. */ @@ -745,18 +511,6 @@ goog.exportProperty( ol.Map.prototype.setBackgroundColor); -/** - * @param {ol.Coordinate|undefined} center Center. - */ -ol.Map.prototype.setCenter = function(center) { - this.set(ol.MapProperty.CENTER, center); -}; -goog.exportProperty( - ol.Map.prototype, - 'setCenter', - ol.Map.prototype.setCenter); - - /** * @param {ol.Collection} layers Layers. */ @@ -769,42 +523,6 @@ goog.exportProperty( ol.Map.prototype.setLayers); -/** - * @param {ol.Projection} projection Projection. - */ -ol.Map.prototype.setProjection = function(projection) { - this.set(ol.MapProperty.PROJECTION, projection); -}; -goog.exportProperty( - ol.Map.prototype, - 'setProjection', - ol.Map.prototype.setProjection); - - -/** - * @param {number|undefined} resolution Resolution. - */ -ol.Map.prototype.setResolution = function(resolution) { - this.set(ol.MapProperty.RESOLUTION, resolution); -}; -goog.exportProperty( - ol.Map.prototype, - 'setResolution', - ol.Map.prototype.setResolution); - - -/** - * @param {number|undefined} rotation Rotation. - */ -ol.Map.prototype.setRotation = function(rotation) { - this.set(ol.MapProperty.ROTATION, rotation); -}; -goog.exportProperty( - ol.Map.prototype, - 'setRotation', - ol.Map.prototype.setRotation); - - /** * @param {ol.Size} size Size. */ @@ -818,23 +536,15 @@ goog.exportProperty( /** - * @param {ol.Coordinate} userCenter Center in user projection. + * @param {ol.IView} view View. */ -ol.Map.prototype.setUserCenter = function(userCenter) { - this.setCenter(this.userToMapTransform_(userCenter)); -}; - - -/** - * @param {ol.Projection} userProjection User projection. - */ -ol.Map.prototype.setUserProjection = function(userProjection) { - this.set(ol.MapProperty.USER_PROJECTION, userProjection); +ol.Map.prototype.setView = function(view) { + this.set(ol.MapProperty.VIEW, view); }; goog.exportProperty( ol.Map.prototype, - 'setUserProjection', - ol.Map.prototype.setUserProjection); + 'setView', + ol.Map.prototype.setView); /** @@ -863,53 +573,9 @@ ol.Map.prototype.withFrozenRendering = function(f, opt_obj) { }; -/** - * @private - * @param {number|undefined} resolution Resolution to go to. - * @param {ol.Coordinate=} opt_anchor Anchor coordinate. - */ -ol.Map.prototype.zoom_ = function(resolution, opt_anchor) { - if (goog.isDefAndNotNull(resolution) && goog.isDefAndNotNull(opt_anchor)) { - var anchor = opt_anchor; - var oldCenter = /** @type {!ol.Coordinate} */ this.getCenter(); - var oldResolution = this.getResolution(); - var x = anchor.x - resolution * (anchor.x - oldCenter.x) / oldResolution; - var y = anchor.y - resolution * (anchor.y - oldCenter.y) / oldResolution; - var center = new ol.Coordinate(x, y); - this.withFrozenRendering(function() { - this.setCenter(center); - this.setResolution(resolution); - }, this); - } else { - this.setResolution(resolution); - } -}; - - -/** - * @param {number} delta Delta from previous zoom level. - * @param {ol.Coordinate=} opt_anchor Anchor coordinate. - */ -ol.Map.prototype.zoom = function(delta, opt_anchor) { - var resolution = this.constraints_.resolution(this.getResolution(), delta); - this.zoom_(resolution, opt_anchor); -}; - - -/** - * @param {number|undefined} resolution Resolution to go to. - * @param {ol.Coordinate=} opt_anchor Anchor coordinate. - */ -ol.Map.prototype.zoomToResolution = function(resolution, opt_anchor) { - resolution = this.constraints_.resolution(resolution, 0); - this.zoom_(resolution, opt_anchor); -}; - - /** * @typedef {{controls: ol.Collection, * interactions: ol.Collection, - * constraints: ol.Constraints, * rendererConstructor: * function(new: ol.renderer.Map, Element, ol.Map), * target: Element, @@ -929,25 +595,11 @@ ol.Map.createOptionsInternal = function(mapOptions) { */ var values = {}; - if (goog.isDef(mapOptions.center)) { - values[ol.MapProperty.CENTER] = mapOptions.center; - } - values[ol.MapProperty.LAYERS] = goog.isDef(mapOptions.layers) ? mapOptions.layers : new ol.Collection(); - values[ol.MapProperty.PROJECTION] = ol.Projection.createProjection( - mapOptions.projection, 'EPSG:3857'); - - if (goog.isDef(mapOptions.resolution)) { - values[ol.MapProperty.RESOLUTION] = mapOptions.resolution; - } else if (goog.isDef(mapOptions.zoom)) { - values[ol.MapProperty.RESOLUTION] = - ol.Projection.EPSG_3857_HALF_SIZE / (128 << mapOptions.zoom); - } - - values[ol.MapProperty.USER_PROJECTION] = ol.Projection.createProjection( - mapOptions.userProjection, 'EPSG:4326'); + values[ol.MapProperty.VIEW] = goog.isDef(mapOptions.view) ? + mapOptions.view : new ol.View2D(); /** * @type {function(new: ol.renderer.Map, Element, ol.Map)} @@ -982,11 +634,6 @@ ol.Map.createOptionsInternal = function(mapOptions) { } } - /** - * @type {ol.Constraints} - */ - var constraints = ol.Map.createConstraints_(mapOptions); - /** * @type {ol.Collection} */ @@ -1013,7 +660,6 @@ ol.Map.createOptionsInternal = function(mapOptions) { var target = goog.dom.getElement(mapOptions.target); return { - constraints: constraints, controls: controls, interactions: interactions, rendererConstructor: rendererConstructor, @@ -1024,40 +670,6 @@ ol.Map.createOptionsInternal = function(mapOptions) { }; -/** - * @private - * @param {ol.MapOptions} mapOptions Map options. - * @return {ol.Constraints} Map constraints. - */ -ol.Map.createConstraints_ = function(mapOptions) { - var resolutionConstraint; - if (goog.isDef(mapOptions.resolutions)) { - resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions( - mapOptions.resolutions); - } else { - var maxResolution, numZoomLevels, zoomFactor; - if (goog.isDef(mapOptions.maxResolution) && - goog.isDef(mapOptions.numZoomLevels) && - goog.isDef(mapOptions.zoomFactor)) { - maxResolution = mapOptions.maxResolution; - numZoomLevels = mapOptions.numZoomLevels; - zoomFactor = mapOptions.zoomFactor; - } else { - maxResolution = ol.Projection.EPSG_3857_HALF_SIZE / 128; - // number of steps we want between two data resolutions - var numSteps = 4; - numZoomLevels = 29 * numSteps; - zoomFactor = Math.exp(Math.log(2) / numSteps); - } - resolutionConstraint = ol.ResolutionConstraint.createSnapToPower( - zoomFactor, maxResolution, numZoomLevels - 1); - } - // FIXME rotation constraint is not configurable at the moment - var rotationConstraint = ol.RotationConstraint.none; - return new ol.Constraints(resolutionConstraint, rotationConstraint); -}; - - /** * @private * @param {ol.MapOptions} mapOptions Map options. diff --git a/src/ol/overlay/overlay.js b/src/ol/overlay/overlay.js index cc9f228feb..1c96bb3d5c 100644 --- a/src/ol/overlay/overlay.js +++ b/src/ol/overlay/overlay.js @@ -43,7 +43,13 @@ ol.overlay.Overlay = function(overlayOptions) { * @private * @type {Array.} */ - this.mapListenerKeys_ = []; + this.mapListenerKeys_ = null; + + /** + * @private + * @type {Array.} + */ + this.viewListenerKeys_ = null; if (goog.isDef(overlayOptions.coordinate)) { this.setCoordinate(overlayOptions.coordinate); @@ -60,6 +66,37 @@ ol.overlay.Overlay = function(overlayOptions) { }; +/** + * @private + */ +ol.overlay.Overlay.prototype.handleViewChanged_ = function() { + goog.asserts.assert(!goog.isNull(this.map_)); + if (!goog.isNull(this.viewListenerKeys_)) { + goog.array.forEach(this.viewListenerKeys_, goog.events.unlistenByKey); + this.viewListenerKeys_ = null; + } + var view = this.map_.getView(); + if (goog.isDefAndNotNull(view)) { + // FIXME works for View2D only + goog.asserts.assert(view instanceof ol.View2D); + this.viewListenerKeys_ = [ + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.CENTER), + this.updatePixelPosition_, false, this), + + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.RESOLUTION), + this.updatePixelPosition_, false, this), + + goog.events.listen( + view, ol.Object.getChangedEventType(ol.View2DProperty.ROTATION), + this.updatePixelPosition_, false, this) + ]; + this.updatePixelPosition_(); + } +}; + + /** * @param {ol.Coordinate} coordinate Coordinate for the overlay's position on * the map. @@ -100,25 +137,24 @@ ol.overlay.Overlay.prototype.getElement = function() { */ ol.overlay.Overlay.prototype.setMap = function(map) { this.map_ = map; - goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey); + if (!goog.isNull(this.mapListenerKeys_)) { + goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey); + this.mapListenerKeys_ = null; + } if (this.element_) { this.setElement(this.element_); } - this.mapListenerKeys_ = map ? [ - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.CENTER), - this.updatePixelPosition_, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION), - this.updatePixelPosition_, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.ROTATION), - this.updatePixelPosition_, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.SIZE), - this.updatePixelPosition_, false, this) - ] : []; - this.updatePixelPosition_(); + if (goog.isDefAndNotNull(map)) { + this.mapListenerKeys_ = [ + goog.events.listen( + map, ol.Object.getChangedEventType(ol.MapProperty.SIZE), + this.updatePixelPosition_, false, this), + goog.events.listen( + map, ol.Object.getChangedEventType(ol.MapProperty.VIEW), + this.handleViewChanged_, false, this) + ]; + this.handleViewChanged_(); + } }; diff --git a/src/ol/renderer/dom/dommaprenderer.js b/src/ol/renderer/dom/dommaprenderer.js index 108f8a2cb9..9122fcf370 100644 --- a/src/ol/renderer/dom/dommaprenderer.js +++ b/src/ol/renderer/dom/dommaprenderer.js @@ -133,26 +133,8 @@ ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) { /** * @inheritDoc */ -ol.renderer.dom.Map.prototype.handleCenterChanged = function() { - goog.base(this, 'handleCenterChanged'); - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Map.prototype.handleResolutionChanged = function() { - goog.base(this, 'handleResolutionChanged'); - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Map.prototype.handleRotationChanged = function() { - goog.base(this, 'handleRotationChanged'); +ol.renderer.dom.Map.prototype.handleViewPropertyChanged = function() { + goog.base(this, 'handleViewPropertyChanged'); this.getMap().render(); }; @@ -166,6 +148,15 @@ ol.renderer.dom.Map.prototype.handleSizeChanged = function() { }; +/** + * @inheritDoc + */ +ol.renderer.dom.Map.prototype.handleViewChanged = function() { + goog.base(this, 'handleViewChanged'); + this.getMap().render(); +}; + + /** * Render the map. Sets up the layers pane on first render and adjusts its * position as needed on subsequent calls. @@ -177,10 +168,11 @@ ol.renderer.dom.Map.prototype.renderFrame = function(time) { return; } - var mapCenter = map.getCenter(); + var view = map.getView().getView2D(); + var mapCenter = view.getCenter(); var mapSize = map.getSize(); - var mapResolution = map.getResolution(); - var mapRotation = map.getRotation(); + var mapResolution = view.getResolution(); + var mapRotation = view.getRotation(); goog.asserts.assert(goog.isDefAndNotNull(mapCenter)); goog.asserts.assert(goog.isDef(mapResolution)); @@ -235,14 +227,15 @@ ol.renderer.dom.Map.prototype.resetLayersPane_ = function() { var mapSize = map.getSize(); var halfWidth = mapSize.width / 2; var halfHeight = mapSize.height / 2; - var center = map.getCenter(); - var resolution = map.getResolution(); + var view = /** @type {ol.View2D} */ (map.getView().getView2D()); + var center = view.getCenter(); + var resolution = view.getResolution(); var origin = new ol.Coordinate( center.x - resolution * halfWidth, center.y + resolution * halfHeight); this.layersPaneOrigin_ = origin; this.setTransformOrigin_(halfWidth, halfHeight); - this.applyTransform_(0, 0, map.getRotation()); + this.applyTransform_(0, 0, view.getRotation()); goog.object.forEach(this.layerRenderers, function(layerRenderer) { layerRenderer.setOrigin(origin); }); @@ -273,8 +266,9 @@ ol.renderer.dom.Map.prototype.setTransformOrigin_ = function(x, y) { */ ol.renderer.dom.Map.prototype.transformLayersPane_ = function() { var map = this.map; - var resolution = map.getResolution(); - var center = map.getCenter(); + var view = map.getView(); + var resolution = view.getResolution(); + var center = view.getCenter(); var size = map.getSize(); var origin = this.layersPaneOrigin_; var ox = (center.x - origin.x) / resolution; @@ -282,5 +276,5 @@ ol.renderer.dom.Map.prototype.transformLayersPane_ = function() { this.setTransformOrigin_(ox, oy); var dx = ox - (size.width / 2); var dy = oy - (size.height / 2); - this.applyTransform_(-dx, -dy, map.getRotation()); + this.applyTransform_(-dx, -dy, view.getRotation()); }; diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 0dc068365d..dcaeaa2b96 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -95,8 +95,10 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) { if (!map.isDef()) { return; } - var mapExtent = /** @type {!ol.Extent} */ map.getRotatedExtent(); - var mapResolution = /** @type {number} */ map.getResolution(); + var mapSize = /** @type {ol.Size} */ (map.getSize()); + var view = map.getView().getView2D(); + var mapExtent = /** @type {!ol.Extent} */ (view.getRotatedExtent(mapSize)); + var mapResolution = /** @type {number} */ (view.getResolution()); var resolutionChanged = (mapResolution !== this.renderedMapResolution_); var tileLayer = this.getLayer(); diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 7f5195818e..8c9de9c479 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -1,11 +1,14 @@ goog.provide('ol.renderer.Map'); goog.require('goog.Disposable'); +goog.require('goog.asserts'); goog.require('goog.events'); goog.require('goog.functions'); goog.require('goog.fx.anim'); goog.require('goog.fx.anim.Animated'); goog.require('goog.vec.Mat4'); +goog.require('ol.View2D'); +goog.require('ol.View2DProperty'); @@ -43,6 +46,13 @@ ol.renderer.Map = function(container, map) { */ this.layersListenerKeys_ = null; + + /** + * @private + * @type {?number} + */ + this.viewPropertyListenerKey_ = null; + /** * @private * @type {goog.vec.Mat4.Number} @@ -70,25 +80,17 @@ ol.renderer.Map = function(container, map) { map, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR), this.handleBackgroundColorChanged, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.CENTER), - this.handleCenterChanged, false, this), - goog.events.listen( map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), this.handleLayersChanged, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION), - this.handleResolutionChanged, false, this), - - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.ROTATION), - this.handleRotationChanged, false, this), - goog.events.listen( map, ol.Object.getChangedEventType(ol.MapProperty.SIZE), - this.handleSizeChanged, false, this) + this.handleSizeChanged, false, this), + + goog.events.listen( + map, ol.Object.getChangedEventType(ol.MapProperty.VIEW), + this.handleViewChanged, false, this) ]; }; @@ -127,6 +129,9 @@ ol.renderer.Map.prototype.disposeInternal = function() { goog.dispose(layerRenderer); }); goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey); + if (!goog.isNull(this.viewPropertyListenerKey_)) { + goog.events.unlistenByKey(this.viewPropertyListenerKey_); + } if (!goog.isNull(this.layersListenerKeys_)) { goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); } @@ -204,14 +209,6 @@ ol.renderer.Map.prototype.getPixelFromCoordinate = function(coordinate) { ol.renderer.Map.prototype.handleBackgroundColorChanged = goog.nullFunction; -/** - * @protected - */ -ol.renderer.Map.prototype.handleCenterChanged = function() { - this.matricesDirty_ = true; -}; - - /** * @param {ol.CollectionEvent} collectionEvent Collection event. * @protected @@ -258,15 +255,7 @@ ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) { /** * @protected */ -ol.renderer.Map.prototype.handleResolutionChanged = function() { - this.matricesDirty_ = true; -}; - - -/** - * @protected - */ -ol.renderer.Map.prototype.handleRotationChanged = function() { +ol.renderer.Map.prototype.handleViewPropertyChanged = function() { this.matricesDirty_ = true; }; @@ -279,6 +268,23 @@ ol.renderer.Map.prototype.handleSizeChanged = function() { }; +/** + * @protected + */ +ol.renderer.Map.prototype.handleViewChanged = function() { + if (!goog.isNull(this.viewPropertyListenerKey_)) { + goog.events.unlistenByKey(this.viewPropertyListenerKey_); + this.viewPropertyListenerKey_ = null; + } + var view = this.getMap().getView(); + if (goog.isDefAndNotNull(view)) { + this.viewPropertyListenerKey_ = goog.events.listen( + view, ol.ObjectEventType.CHANGED, + this.handleViewPropertyChanged, false, this); + } +}; + + /** * @param {ol.layer.Layer} layer Layer. * @protected @@ -332,10 +338,11 @@ ol.renderer.Map.prototype.updateMatrices_ = function() { if (this.matricesDirty_) { var map = this.map; - var center = /** @type {!ol.Coordinate} */ map.getCenter(); - var resolution = /** @type {number} */ map.getResolution(); - var rotation = map.getRotation(); - var size = /** @type {!ol.Size} */ map.getSize(); + var view = map.getView().getView2D(); + var center = /** @type {!ol.Coordinate} */ (view.getCenter()); + var resolution = /** @type {number} */ (view.getResolution()); + var rotation = view.getRotation(); + var size = /** @type {!ol.Size} */ (map.getSize()); goog.vec.Mat4.makeIdentity(this.coordinateToPixelMatrix_); goog.vec.Mat4.translate(this.coordinateToPixelMatrix_, diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 9b0b638e62..c32b09c9cc 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -386,8 +386,8 @@ ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() { /** * @inheritDoc */ -ol.renderer.webgl.Map.prototype.handleCenterChanged = function() { - goog.base(this, 'handleCenterChanged'); +ol.renderer.webgl.Map.prototype.handleViewPropertyChanged = function() { + goog.base(this, 'handleViewPropertyChanged'); this.getMap().render(); }; @@ -401,24 +401,6 @@ ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.handleResolutionChanged = function() { - goog.base(this, 'handleResolutionChanged'); - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.handleRotationChanged = function() { - goog.base(this, 'handleRotationChanged'); - this.getMap().render(); -}; - - /** * @inheritDoc */ @@ -428,6 +410,15 @@ ol.renderer.webgl.Map.prototype.handleSizeChanged = function() { }; +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.handleViewChanged = function() { + goog.base(this, 'handleViewChanged'); + this.getMap().render(); +}; + + /** * @param {goog.events.Event} event Event. * @protected @@ -525,7 +516,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(time) { } }); - var size = /** @type {ol.Size} */ this.getMap().getSize(); + var size = /** @type {ol.Size} */ (this.getMap().getSize()); if (!this.canvasSize_.equals(size)) { this.canvas_.width = size.width; this.canvas_.height = size.height; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 391bfd6d4f..b43cf8710f 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -294,13 +294,15 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) { var mapRenderer = this.getMapRenderer(); var map = this.getMap(); var gl = mapRenderer.getGL(); + var view = map.getView().getView2D(); goog.asserts.assert(map.isDef()); - var mapCenter = map.getCenter(); - var mapExtent = map.getExtent(); - var mapResolution = /** @type {number} */ map.getResolution(); - var mapRotatedExtent = map.getRotatedExtent(); - var mapRotation = map.getRotation(); + var mapSize = map.getSize(); + var mapCenter = view.getCenter(); + var mapExtent = view.getExtent(mapSize); + var mapResolution = /** @type {number} */ (view.getResolution()); + var mapRotatedExtent = view.getRotatedExtent(mapSize); + var mapRotation = view.getRotation(); var tileLayer = this.getLayer(); var tileSource = tileLayer.getTileSource(); diff --git a/src/ol/view.js b/src/ol/view.js new file mode 100644 index 0000000000..b155d8ae15 --- /dev/null +++ b/src/ol/view.js @@ -0,0 +1,29 @@ +goog.provide('ol.View'); + +goog.require('ol.IView'); +goog.require('ol.IView2D'); +goog.require('ol.IView3D'); + + + +/** + * @constructor + * @implements {ol.IView} + * @extends {ol.Object} + */ +ol.View = function() { +}; +goog.inherits(ol.View, ol.Object); + + +/** + * @inheritDoc + */ +ol.View.prototype.getView2D = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.View.prototype.getView3D = goog.abstractMethod; + diff --git a/src/ol/view2d.js b/src/ol/view2d.js new file mode 100644 index 0000000000..998b226196 --- /dev/null +++ b/src/ol/view2d.js @@ -0,0 +1,344 @@ +// FIXME getView3D has not return type + +goog.provide('ol.View2D'); +goog.provide('ol.View2DProperty'); + +goog.require('ol.Constraints'); +goog.require('ol.Extent'); +goog.require('ol.IView2D'); +goog.require('ol.IView3D'); +goog.require('ol.Projection'); +goog.require('ol.ResolutionConstraint'); +goog.require('ol.RotationConstraint'); +goog.require('ol.View'); + + +/** + * @enum {string} + */ +ol.View2DProperty = { + CENTER: 'center', + PROJECTION: 'projection', + RESOLUTION: 'resolution', + ROTATION: 'rotation' +}; + + + +/** + * @constructor + * @implements {ol.IView2D} + * @implements {ol.IView3D} + * @extends {ol.View} + * @param {ol.View2DOptions=} opt_view2DOptions View2D options. + */ +ol.View2D = function(opt_view2DOptions) { + goog.base(this); + var view2DOptions = opt_view2DOptions || {}; + + /** + * @type {Object.} + */ + var values = {}; + values[ol.View2DProperty.CENTER] = goog.isDef(view2DOptions.center) ? + view2DOptions.center : null; + values[ol.View2DProperty.PROJECTION] = ol.Projection.createProjection( + view2DOptions.projection, 'EPSG:3857'); + if (goog.isDef(view2DOptions.resolution)) { + values[ol.View2DProperty.RESOLUTION] = view2DOptions.resolution; + } else if (goog.isDef(view2DOptions.zoom)) { + values[ol.View2DProperty.RESOLUTION] = + ol.Projection.EPSG_3857_HALF_SIZE / (128 << view2DOptions.zoom); + } + values[ol.View2DProperty.ROTATION] = view2DOptions.rotation; + this.setValues(values); + + /** + * @private + * @type {ol.Constraints} + */ + this.constraints_ = ol.View2D.createConstraints_(view2DOptions); + +}; +goog.inherits(ol.View2D, ol.View); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getCenter = function() { + return /** @type {ol.Coordinate|undefined} */ ( + this.get(ol.View2DProperty.CENTER)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getCenter', + ol.View2D.prototype.getCenter); + + +/** + * @param {ol.Size} size Box pixel size. + * @return {ol.Extent} Extent. + */ +ol.View2D.prototype.getExtent = function(size) { + goog.asserts.assert(this.isDef()); + var center = this.getCenter(); + var resolution = this.getResolution(); + var minX = center.x - resolution * size.width / 2; + var minY = center.y - resolution * size.height / 2; + var maxX = center.x + resolution * size.width / 2; + var maxY = center.y + resolution * size.height / 2; + return new ol.Extent(minX, minY, maxX, maxY); +}; + + +/** + * @param {ol.Size} size Box pixel size. + * @return {ol.Extent} Rotated extent. + */ +ol.View2D.prototype.getRotatedExtent = function(size) { + goog.asserts.assert(this.isDef()); + // FIXME try w/o casting + var center = /** @type {!ol.Coordinate} */ (this.getCenter()); + var resolution = this.getResolution(); + var rotation = this.getRotation(); + var xScale = resolution * size.width / 2; + var yScale = resolution * size.height / 2; + var corners = [ + new ol.Coordinate(-xScale, -yScale), + new ol.Coordinate(-xScale, yScale), + new ol.Coordinate(xScale, -yScale), + new ol.Coordinate(xScale, yScale) + ]; + goog.array.forEach(corners, function(corner) { + corner.rotate(rotation); + corner.add(center); + }); + return ol.Extent.boundingExtent.apply(null, corners); +}; + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getProjection = function() { + return /** @type {ol.Projection|undefined} */ ( + this.get(ol.View2DProperty.PROJECTION)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getProjection', + ol.View2D.prototype.getProjection); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getResolution = function() { + return /** @type {number|undefined} */ ( + this.get(ol.View2DProperty.RESOLUTION)); +}; +goog.exportProperty( + ol.View2D.prototype, + 'getResolution', + ol.View2D.prototype.getResolution); + + +/** + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Box pixel size. + * @return {number} Resolution. + */ +ol.View2D.prototype.getResolutionForExtent = function(extent, size) { + var xResolution = (extent.maxX - extent.minX) / size.width; + var yResolution = (extent.maxY - extent.minY) / size.height; + return Math.max(xResolution, yResolution); +}; + + +/** + * @return {number} Map rotation. + */ +ol.View2D.prototype.getRotation = function() { + return /** @type {number|undefined} */ ( + this.get(ol.View2DProperty.ROTATION)) || 0; +}; +goog.exportProperty( + ol.View2D.prototype, + 'getRotation', + ol.View2D.prototype.getRotation); + + +/** + * @inheritDoc + */ +ol.View2D.prototype.getView2D = function() { + return this; +}; + + +/** + * FIXME return type + */ +ol.View2D.prototype.getView3D = function() { +}; + + +/** + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Box pixel size. + */ +ol.View2D.prototype.fitExtent = function(extent, size) { + this.setCenter(extent.getCenter()); + var resolution = this.getResolutionForExtent(extent, size); + resolution = this.constraints_.resolution(resolution, 0); + this.setResolution(resolution); +}; + + +/** + * @return {boolean} Is defined. + */ +ol.View2D.prototype.isDef = function() { + return goog.isDefAndNotNull(this.getCenter()) && + goog.isDef(this.getResolution()); +}; + + +/** + * @param {ol.Coordinate|undefined} center Center. + */ +ol.View2D.prototype.setCenter = function(center) { + this.set(ol.View2DProperty.CENTER, center); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setCenter', + ol.View2D.prototype.setCenter); + + +/** + * @param {ol.Projection|undefined} projection Projection. + */ +ol.View2D.prototype.setProjection = function(projection) { + this.set(ol.View2DProperty.PROJECTION, projection); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setProjection', + ol.View2D.prototype.setProjection); + + +/** + * @param {number|undefined} resolution Resolution. + */ +ol.View2D.prototype.setResolution = function(resolution) { + this.set(ol.View2DProperty.RESOLUTION, resolution); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setResolution', + ol.View2D.prototype.setResolution); + + +/** + * @param {number|undefined} rotation Rotation. + */ +ol.View2D.prototype.setRotation = function(rotation) { + this.set(ol.View2DProperty.ROTATION, rotation); +}; +goog.exportProperty( + ol.View2D.prototype, + 'setRotation', + ol.View2D.prototype.setRotation); + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + */ +ol.View2D.prototype.rotate = function(map, rotation, delta) { + rotation = this.constraints_.rotation(rotation, delta); + this.setRotation(rotation); +}; + + +/** + * @private + * @param {ol.Map} map Map. + * @param {number|undefined} resolution Resolution to go to. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + */ +ol.View2D.prototype.zoom_ = function(map, resolution, opt_anchor) { + if (goog.isDefAndNotNull(resolution) && goog.isDefAndNotNull(opt_anchor)) { + var anchor = opt_anchor; + var oldCenter = /** @type {!ol.Coordinate} */ (this.getCenter()); + var oldResolution = this.getResolution(); + var x = anchor.x - resolution * (anchor.x - oldCenter.x) / oldResolution; + var y = anchor.y - resolution * (anchor.y - oldCenter.y) / oldResolution; + var center = new ol.Coordinate(x, y); + map.withFrozenRendering(function() { + this.setCenter(center); + this.setResolution(resolution); + }, this); + } else { + this.setResolution(resolution); + } +}; + + +/** + * @param {ol.Map} map Map. + * @param {number} delta Delta from previous zoom level. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + */ +ol.View2D.prototype.zoom = function(map, delta, opt_anchor) { + var resolution = this.constraints_.resolution(this.getResolution(), delta); + this.zoom_(map, resolution, opt_anchor); +}; + + +/** + * @param {ol.Map} map Map. + * @param {number|undefined} resolution Resolution to go to. + * @param {ol.Coordinate=} opt_anchor Anchor coordinate. + */ +ol.View2D.prototype.zoomToResolution = function(map, resolution, opt_anchor) { + resolution = this.constraints_.resolution(resolution, 0); + this.zoom_(map, resolution, opt_anchor); +}; + + +/** + * @private + * @param {ol.View2DOptions} view2DOptions View2D options. + * @return {ol.Constraints} Constraints. + */ +ol.View2D.createConstraints_ = function(view2DOptions) { + var resolutionConstraint; + if (goog.isDef(view2DOptions.resolutions)) { + resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions( + view2DOptions.resolutions); + } else { + var maxResolution, numZoomLevels, zoomFactor; + if (goog.isDef(view2DOptions.maxResolution) && + goog.isDef(view2DOptions.numZoomLevels) && + goog.isDef(view2DOptions.zoomFactor)) { + maxResolution = view2DOptions.maxResolution; + numZoomLevels = view2DOptions.numZoomLevels; + zoomFactor = view2DOptions.zoomFactor; + } else { + maxResolution = ol.Projection.EPSG_3857_HALF_SIZE / 128; + // number of steps we want between two data resolutions + var numSteps = 4; + numZoomLevels = 29 * numSteps; + zoomFactor = Math.exp(Math.log(2) / numSteps); + } + resolutionConstraint = ol.ResolutionConstraint.createSnapToPower( + zoomFactor, maxResolution, numZoomLevels - 1); + } + // FIXME rotation constraint is not configurable at the moment + var rotationConstraint = ol.RotationConstraint.none; + return new ol.Constraints(resolutionConstraint, rotationConstraint); +}; diff --git a/test/ol.html b/test/ol.html index 08793ee015..9c00d22ecd 100644 --- a/test/ol.html +++ b/test/ol.html @@ -78,6 +78,7 @@ + diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index 1ce6d9f694..b30207e771 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -4,6 +4,7 @@ goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.RendererHint'); +goog.require('ol.View2D'); goog.require('ol.layer.TileLayer'); goog.require('ol.source.XYZ'); @@ -24,56 +25,6 @@ describe('ol.Map', function() { }); }); - describe('create constraints', function() { - - describe('create resolution constraint', function() { - - describe('with no options', function() { - it('gives a correct resolution constraint function', function() { - var options = {}; - var fn = ol.Map.createConstraints_(options).resolution; - expect(fn(156543.03392804097, 0)) - .toRoughlyEqual(156543.03392804097, 1e-9); - expect(fn(78271.51696402048, 0)) - .toRoughlyEqual(78271.51696402048, 1e-10); - }); - }); - - describe('with maxResolution, numZoomLevels, and zoomFactor options', - function() { - it('gives a correct resolution constraint function', function() { - var options = { - maxResolution: 81, - numZoomLevels: 4, - zoomFactor: 3 - }; - var fn = ol.Map.createConstraints_(options).resolution; - expect(fn(82, 0)).toEqual(81); - expect(fn(81, 0)).toEqual(81); - expect(fn(27, 0)).toEqual(27); - expect(fn(9, 0)).toEqual(9); - expect(fn(3, 0)).toEqual(3); - expect(fn(2, 0)).toEqual(3); - }); - }); - - describe('with resolutions', function() { - it('gives a correct resolution constraint function', function() { - var options = { - resolutions: [97, 76, 65, 54, 0.45] - }; - var fn = ol.Map.createConstraints_(options).resolution; - expect(fn(97, 0), 97); - expect(fn(76, 0), 76); - expect(fn(65, 0), 65); - expect(fn(54, 0), 54); - expect(fn(0.45, 0), 0.45); - }); - }); - - }); - }); - describe('create interactions', function() { var options; @@ -158,11 +109,13 @@ describe('ol.Map', function() { }); map = new ol.Map({ - center: new ol.Coordinate(0, 0), layers: new ol.Collection([layer]), renderer: ol.RendererHint.DOM, target: 'map', - zoom: 1 + view: new ol.View2D({ + center: new ol.Coordinate(0, 0), + zoom: 1 + }) }); }); @@ -183,7 +136,7 @@ describe('ol.Map', function() { var duration = 500; var destination = new ol.Coordinate(1000, 1000); - var origin = map.getCenter(); + var origin = map.getView().getCenter(); var start = new Date().getTime(); var x0 = origin.x; var y0 = origin.y; @@ -202,7 +155,7 @@ describe('ol.Map', function() { x = destination.x; y = destination.y; } - map.setCenter(new ol.Coordinate(x, y)); + map.getView().setCenter(new ol.Coordinate(x, y)); if (more) { animationDelay.start(); } @@ -220,7 +173,7 @@ describe('ol.Map', function() { waits(100); runs(function() { expect(o.callback).toHaveBeenCalled(); - var loc = map.getCenter(); + var loc = map.getView().getCenter(); expect(loc.x).not.toEqual(origin.x); expect(loc.y).not.toEqual(origin.y); expect(loc.x).not.toEqual(destination.x); @@ -230,7 +183,7 @@ describe('ol.Map', function() { // confirm that the map has reached the destination after the duration waits(duration); runs(function() { - var loc = map.getCenter(); + var loc = map.getView().getCenter(); expect(loc.x).toEqual(destination.x); expect(loc.y).toEqual(destination.y); }); diff --git a/test/spec/ol/view2d.test.js b/test/spec/ol/view2d.test.js new file mode 100644 index 0000000000..c4ea5ad57a --- /dev/null +++ b/test/spec/ol/view2d.test.js @@ -0,0 +1,53 @@ +goog.require('ol.View2D'); + +describe('ol.View2D', function() { + describe('create constraints', function() { + + describe('create resolution constraint', function() { + + describe('with no options', function() { + it('gives a correct resolution constraint function', function() { + var options = {}; + var fn = ol.View2D.createConstraints_(options).resolution; + expect(fn(156543.03392804097, 0)) + .toRoughlyEqual(156543.03392804097, 1e-9); + expect(fn(78271.51696402048, 0)) + .toRoughlyEqual(78271.51696402048, 1e-10); + }); + }); + + describe('with maxResolution, numZoomLevels, and zoomFactor options', + function() { + it('gives a correct resolution constraint function', function() { + var options = { + maxResolution: 81, + numZoomLevels: 4, + zoomFactor: 3 + }; + var fn = ol.View2D.createConstraints_(options).resolution; + expect(fn(82, 0)).toEqual(81); + expect(fn(81, 0)).toEqual(81); + expect(fn(27, 0)).toEqual(27); + expect(fn(9, 0)).toEqual(9); + expect(fn(3, 0)).toEqual(3); + expect(fn(2, 0)).toEqual(3); + }); + }); + + describe('with resolutions', function() { + it('gives a correct resolution constraint function', function() { + var options = { + resolutions: [97, 76, 65, 54, 0.45] + }; + var fn = ol.View2D.createConstraints_(options).resolution; + expect(fn(97, 0)).toEqual(97); + expect(fn(76, 0)).toEqual(76); + expect(fn(65, 0)).toEqual(65); + expect(fn(54, 0)).toEqual(54); + expect(fn(0.45, 0)).toEqual(0.45); + }); + }); + + }); + }); +});