Merge branch 'master' of github.com:openlayers/ol3 into vector
This commit is contained in:
@@ -78,8 +78,8 @@
|
||||
}
|
||||
}
|
||||
.ol-zoom-in {
|
||||
border-radius: 4px 4px 0 0;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
.ol-zoom-out {
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
margin-left: -13px;
|
||||
}
|
||||
</style>
|
||||
<title>Overlay example</title>
|
||||
<title>Anchored elements example</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map">
|
||||
@@ -89,16 +89,16 @@
|
||||
<!-- Popup -->
|
||||
<div class="overlay arrow_box" id="popup"></div>
|
||||
<div id="text">
|
||||
<h1 id="title">Overlay example</h1>
|
||||
<div id="shortdesc">Demonstrates Overlays.</div>
|
||||
<h1 id="title">Anchored elements example</h1>
|
||||
<div id="shortdesc">Demonstrates anchored elements.</div>
|
||||
<div id="docs">
|
||||
<p>See the
|
||||
<a href="overlay-and-popup.js" target="_blank">overlay-and-popup.js source</a>
|
||||
<a href="anchored-elements.js" target="_blank">anchored-elements.js source</a>
|
||||
to see how this is done.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tags">overlay, popup, mapquest, openaerial</div>
|
||||
<script src="loader.js?id=overlay-and-popup" type="text/javascript"></script>
|
||||
<div id="tags">anchored elements, overlay, popup, mapquest, openaerial</div>
|
||||
<script src="loader.js?id=anchored-elements" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +1,12 @@
|
||||
goog.require('goog.debug.Console');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.debug.Logger.Level');
|
||||
goog.require('ol.AnchoredElement');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.RendererHints');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.overlay.Overlay');
|
||||
goog.require('ol.source.MapQuestOpenAerial');
|
||||
|
||||
|
||||
@@ -31,15 +31,15 @@ var map = new ol.Map({
|
||||
});
|
||||
|
||||
// Vienna label
|
||||
var vienna = new ol.overlay.Overlay({
|
||||
var vienna = new ol.AnchoredElement({
|
||||
map: map,
|
||||
coordinate: ol.Projection.transformWithCodes(
|
||||
position: ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(16.3725, 48.208889), 'EPSG:4326', 'EPSG:3857'),
|
||||
element: document.getElementById('vienna')
|
||||
});
|
||||
|
||||
// Popup showing the position the user clicked
|
||||
var popup = new ol.overlay.Overlay({
|
||||
var popup = new ol.AnchoredElement({
|
||||
map: map,
|
||||
element: document.getElementById('popup')
|
||||
});
|
||||
@@ -49,5 +49,5 @@ map.addEventListener('click', function(evt) {
|
||||
'Welcome to ol3. The location you clicked was<br>' +
|
||||
ol.Coordinate.toStringHDMS(ol.Projection.transformWithCodes(
|
||||
coordinate, 'EPSG:3857', 'EPSG:4326'));
|
||||
popup.setCoordinate(coordinate);
|
||||
popup.setPosition(coordinate);
|
||||
});
|
||||
@@ -45,7 +45,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rotate:</td>
|
||||
<td><code>Alt</code>+drag, <code>r</code> to reset</td>
|
||||
<td><code>Alt+Shift</code>+drag, <code>r</code> to reset</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Brightness/contrast:</td>
|
||||
|
||||
@@ -107,25 +107,41 @@ keyboardInteraction.addCallback('H', function() {
|
||||
layer.setHue(layer.getHue() + (Math.PI / 5));
|
||||
});
|
||||
keyboardInteraction.addCallback('j', function() {
|
||||
var bounce = ol.animation.createBounce(2 * view.getResolution());
|
||||
var bounce = ol.animation.createBounce({
|
||||
resolution: 2 * view.getResolution()
|
||||
});
|
||||
domMap.addPreRenderFunction(bounce);
|
||||
webglMap.addPreRenderFunction(bounce);
|
||||
canvasMap.addPreRenderFunction(bounce);
|
||||
});
|
||||
keyboardInteraction.addCallback('l', function() {
|
||||
var panFrom = ol.animation.createPanFrom(view.getCenter());
|
||||
var panFrom = ol.animation.createPanFrom({
|
||||
source: view.getCenter(),
|
||||
easing: ol.easing.elastic
|
||||
});
|
||||
domMap.addPreRenderFunction(panFrom);
|
||||
webglMap.addPreRenderFunction(panFrom);
|
||||
canvasMap.addPreRenderFunction(panFrom);
|
||||
view.setCenter(LONDON);
|
||||
});
|
||||
keyboardInteraction.addCallback('L', function() {
|
||||
var start = Date.now();
|
||||
var start = goog.now();
|
||||
var duration = 5000;
|
||||
var bounce = ol.animation.createBounce(
|
||||
2 * view.getResolution(), duration, start);
|
||||
var panFrom = ol.animation.createPanFrom(view.getCenter(), duration, start);
|
||||
var spin = ol.animation.createSpin(duration, 2, start);
|
||||
var bounce = ol.animation.createBounce({
|
||||
resolution: 2 * view.getResolution(),
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var panFrom = ol.animation.createPanFrom({
|
||||
source: view.getCenter(),
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var spin = ol.animation.createSpin({
|
||||
turns: 2,
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var preRenderFunctions = [bounce, panFrom, spin];
|
||||
domMap.addPreRenderFunctions(preRenderFunctions);
|
||||
webglMap.addPreRenderFunctions(preRenderFunctions);
|
||||
@@ -133,19 +149,34 @@ keyboardInteraction.addCallback('L', function() {
|
||||
view.setCenter(LONDON);
|
||||
});
|
||||
keyboardInteraction.addCallback('m', function() {
|
||||
var panFrom = ol.animation.createPanFrom(view.getCenter(), 1000);
|
||||
var panFrom = ol.animation.createPanFrom({
|
||||
source: view.getCenter(),
|
||||
duration: 1000,
|
||||
easing: ol.easing.bounce
|
||||
});
|
||||
domMap.addPreRenderFunction(panFrom);
|
||||
webglMap.addPreRenderFunction(panFrom);
|
||||
canvasMap.addPreRenderFunction(panFrom);
|
||||
view.setCenter(MOSCOW);
|
||||
});
|
||||
keyboardInteraction.addCallback('M', function() {
|
||||
var start = Date.now();
|
||||
var start = goog.now();
|
||||
var duration = 5000;
|
||||
var bounce = ol.animation.createBounce(
|
||||
2 * view.getResolution(), duration, start);
|
||||
var panFrom = ol.animation.createPanFrom(view.getCenter(), duration, start);
|
||||
var spin = ol.animation.createSpin(duration, -2, start);
|
||||
var bounce = ol.animation.createBounce({
|
||||
resolution: 2 * view.getResolution(),
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var panFrom = ol.animation.createPanFrom({
|
||||
source: view.getCenter(),
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var spin = ol.animation.createSpin({
|
||||
turns: -2,
|
||||
start: start,
|
||||
duration: duration
|
||||
});
|
||||
var preRenderFunctions = [bounce, panFrom, spin];
|
||||
domMap.addPreRenderFunctions(preRenderFunctions);
|
||||
webglMap.addPreRenderFunctions(preRenderFunctions);
|
||||
@@ -172,13 +203,19 @@ keyboardInteraction.addCallback('vV', function() {
|
||||
layer.setVisible(!layer.getVisible());
|
||||
});
|
||||
keyboardInteraction.addCallback('x', function() {
|
||||
var spin = ol.animation.createSpin(2000, 2);
|
||||
var spin = ol.animation.createSpin({
|
||||
turns: 2,
|
||||
duration: 2000
|
||||
});
|
||||
domMap.addPreRenderFunction(spin);
|
||||
webglMap.addPreRenderFunction(spin);
|
||||
canvasMap.addPreRenderFunction(spin);
|
||||
});
|
||||
keyboardInteraction.addCallback('X', function() {
|
||||
var spin = ol.animation.createSpin(2000, -2);
|
||||
var spin = ol.animation.createSpin({
|
||||
turns: -2,
|
||||
duration: 2000
|
||||
});
|
||||
domMap.addPreRenderFunction(spin);
|
||||
webglMap.addPreRenderFunction(spin);
|
||||
canvasMap.addPreRenderFunction(spin);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<tr>
|
||||
<th>DOM</th>
|
||||
<th>WebGL</th>
|
||||
<th>Canvas</th>
|
||||
<th>Canvas <a id="canvas-export" href="#" download="map.jpeg">export map as jpeg</a></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div id="domMap" class="map"></div></td>
|
||||
|
||||
@@ -48,3 +48,7 @@ var canvasMap = new ol.Map({
|
||||
});
|
||||
canvasMap.bindTo('layers', webglMap);
|
||||
canvasMap.bindTo('view', webglMap);
|
||||
|
||||
goog.events.listen(goog.dom.getElement('canvas-export'), 'click', function(e) {
|
||||
e.target.href = canvasMap.getRenderer().getCanvas().toDataURL('image/jpeg');
|
||||
});
|
||||
|
||||
@@ -52,9 +52,6 @@ var layers = new ol.Collection([
|
||||
]);
|
||||
|
||||
var map = new ol.Map({
|
||||
// By setting userProjection to the same as projection, we do not need
|
||||
// proj4js because we do not need any transforms.
|
||||
userProjection: epsg21781,
|
||||
layers: layers,
|
||||
renderers: ol.RendererHints.createFromQueryData(),
|
||||
target: 'map',
|
||||
|
||||
11
readme.md
11
readme.md
@@ -2,13 +2,18 @@
|
||||
|
||||
[](http://travis-ci.org/#!/openlayers/ol3)
|
||||
|
||||
## Build it
|
||||
|
||||
Run make:
|
||||
## Hosted Examples
|
||||
|
||||
The examples are hosted on GitHub (as GitHub pages). See http://openlayers.github.com/ol3/master/examples/.
|
||||
|
||||
## Build OpenLayers 3
|
||||
|
||||
Run build.py:
|
||||
|
||||
$ ./build.py
|
||||
|
||||
## Run the examples in debug mode
|
||||
## Run examples locally
|
||||
|
||||
Run the [Plovr](http://plovr.com/) web server with:
|
||||
|
||||
|
||||
@@ -1,3 +1,55 @@
|
||||
@exportObjectLiteral ol.MapOptions
|
||||
@exportObjectLiteralProperty ol.MapOptions.controls ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.doubleClickZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.dragPan boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.interactions ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.keyboard boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.keyboardPanOffset number|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.layers ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.mouseWheelZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.mouseWheelZoomDelta number|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.renderer ol.RendererHint|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.renderers Array.<ol.RendererHint>|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.target Element|string
|
||||
@exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.zoomDelta number|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.<number>|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.rotation number|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.zoom number|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.zoomFactor number|undefined
|
||||
|
||||
@exportObjectLiteral ol.animation.BounceOptions
|
||||
@exportObjectLiteralProperty ol.animation.BounceOptions.resolution number
|
||||
@exportObjectLiteralProperty ol.animation.BounceOptions.start number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.BounceOptions.duration number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.BounceOptions.easing function(number):number|undefined
|
||||
|
||||
@exportObjectLiteral ol.animation.PanFromOptions
|
||||
@exportObjectLiteralProperty ol.animation.PanFromOptions.source ol.Coordinate
|
||||
@exportObjectLiteralProperty ol.animation.PanFromOptions.start number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.PanFromOptions.duration number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.PanFromOptions.easing function(number):number|undefined
|
||||
|
||||
@exportObjectLiteral ol.animation.SpinOptions
|
||||
@exportObjectLiteralProperty ol.animation.SpinOptions.turns number
|
||||
@exportObjectLiteralProperty ol.animation.SpinOptions.start number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.SpinOptions.duration number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.SpinOptions.easing function(number):number|undefined
|
||||
|
||||
@exportObjectLiteral ol.animation.ZoomFromOptions
|
||||
@exportObjectLiteralProperty ol.animation.ZoomFromOptions.resolution number
|
||||
@exportObjectLiteralProperty ol.animation.ZoomFromOptions.start number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.ZoomFromOptions.duration number|undefined
|
||||
@exportObjectLiteralProperty ol.animation.ZoomFromOptions.easing function(number):number|undefined
|
||||
|
||||
@exportObjectLiteral ol.control.AttributionOptions
|
||||
@exportObjectLiteralProperty ol.control.AttributionOptions.map ol.Map|undefined
|
||||
@exportObjectLiteralProperty ol.control.AttributionOptions.target Element|undefined
|
||||
@@ -23,34 +75,22 @@
|
||||
@exportObjectLiteralProperty ol.layer.LayerOptions.source ol.source.Source
|
||||
@exportObjectLiteralProperty ol.layer.LayerOptions.visible boolean|undefined
|
||||
|
||||
@exportObjectLiteral ol.MapOptions
|
||||
@exportObjectLiteralProperty ol.MapOptions.controls ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.doubleClickZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.dragPan boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.interactions ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.keyboard boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.keyboardPanOffset number|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.layers ol.Collection|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.mouseWheelZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.mouseWheelZoomDelta number|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.renderer ol.RendererHint|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.renderers Array.<ol.RendererHint>|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.target Element|string
|
||||
@exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined
|
||||
@exportObjectLiteralProperty ol.MapOptions.zoomDelta number|undefined
|
||||
|
||||
@exportObjectLiteral ol.overlay.OverlayOptions
|
||||
@exportObjectLiteralProperty ol.overlay.OverlayOptions.coordinate ol.Coordinate|undefined
|
||||
@exportObjectLiteralProperty ol.overlay.OverlayOptions.element Element|undefined
|
||||
@exportObjectLiteralProperty ol.overlay.OverlayOptions.map ol.Map|undefined
|
||||
@exportObjectLiteralProperty ol.overlay.OverlayOptions.positioning Array.<string>|undefined
|
||||
@exportObjectLiteral ol.AnchoredElementOptions
|
||||
@exportObjectLiteralProperty ol.AnchoredElementOptions.element Element|undefined
|
||||
@exportObjectLiteralProperty ol.AnchoredElementOptions.map ol.Map|undefined
|
||||
@exportObjectLiteralProperty ol.AnchoredElementOptions.position ol.Coordinate|undefined
|
||||
@exportObjectLiteralProperty ol.AnchoredElementOptions.positioning ol.AnchoredElementPositioning|undefined
|
||||
|
||||
@exportObjectLiteral ol.source.BingMapsOptions
|
||||
@exportObjectLiteralProperty ol.source.BingMapsOptions.culture string|undefined
|
||||
@exportObjectLiteralProperty ol.source.BingMapsOptions.key string
|
||||
@exportObjectLiteralProperty ol.source.BingMapsOptions.style ol.BingMapsStyle
|
||||
|
||||
@exportObjectLiteral ol.source.DebugTileSourceOptions
|
||||
@exportObjectLiteralProperty ol.source.DebugTileSourceOptions.extent ol.Extent|undefined
|
||||
@exportObjectLiteralProperty ol.source.DebugTileSourceOptions.projection ol.Projection|undefined
|
||||
@exportObjectLiteralProperty ol.source.DebugTileSourceOptions.tileGrid ol.tilegrid.TileGrid|undefined
|
||||
|
||||
@exportObjectLiteral ol.source.StamenOptions
|
||||
@exportObjectLiteralProperty ol.source.StamenOptions.flavor string|undefined
|
||||
@exportObjectLiteralProperty ol.source.StamenOptions.provider string
|
||||
@@ -76,14 +116,3 @@
|
||||
|
||||
@exportObjectLiteral ol.tilegrid.XYZOptions
|
||||
@exportObjectLiteralProperty ol.tilegrid.XYZOptions.maxZoom number
|
||||
|
||||
@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.<number>|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.rotation number|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.zoom number|undefined
|
||||
@exportObjectLiteralProperty ol.View2DOptions.zoomFactor number|undefined
|
||||
|
||||
7
src/ol/anchoredelement.exports
Normal file
7
src/ol/anchoredelement.exports
Normal file
@@ -0,0 +1,7 @@
|
||||
@exportClass ol.AnchoredElement ol.AnchoredElementOptions
|
||||
|
||||
@exportSymbol ol.AnchoredElementPositioning
|
||||
@exportProperty ol.AnchoredElementPositioning.BOTTOM_LEFT
|
||||
@exportProperty ol.AnchoredElementPositioning.BOTTOM_RIGHT
|
||||
@exportProperty ol.AnchoredElementPositioning.TOP_LEFT
|
||||
@exportProperty ol.AnchoredElementPositioning.TOP_RIGHT
|
||||
318
src/ol/anchoredelement.js
Normal file
318
src/ol/anchoredelement.js
Normal file
@@ -0,0 +1,318 @@
|
||||
goog.provide('ol.AnchoredElement');
|
||||
goog.provide('ol.AnchoredElementPositioning');
|
||||
goog.provide('ol.AnchoredElementProperty');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapEventType');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.AnchoredElementProperty = {
|
||||
ELEMENT: 'element',
|
||||
MAP: 'map',
|
||||
POSITION: 'position',
|
||||
POSITIONING: 'positioning'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.AnchoredElementPositioning = {
|
||||
BOTTOM_LEFT: 'bottom-left',
|
||||
BOTTOM_RIGHT: 'bottom-right',
|
||||
TOP_LEFT: 'top-left',
|
||||
TOP_RIGHT: 'top-right'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {ol.AnchoredElementOptions} anchoredElementOptions Anchored element
|
||||
* options.
|
||||
*/
|
||||
ol.AnchoredElement = function(anchoredElementOptions) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.element_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.element_.style.position = 'absolute';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{bottom_: string,
|
||||
* left_: string,
|
||||
* right_: string,
|
||||
* top_: string,
|
||||
* visible: boolean}}
|
||||
*/
|
||||
this.rendered_ = {
|
||||
bottom_: '',
|
||||
left_: '',
|
||||
right_: '',
|
||||
top_: '',
|
||||
visible: true
|
||||
};
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.ELEMENT),
|
||||
this.handleElementChanged, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.MAP),
|
||||
this.handleMapChanged, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.AnchoredElementProperty.POSITION),
|
||||
this.handlePositionChanged, false, this);
|
||||
|
||||
goog.events.listen(
|
||||
this,
|
||||
ol.Object.getChangedEventType(ol.AnchoredElementProperty.POSITIONING),
|
||||
this.handlePositioningChanged, false, this);
|
||||
|
||||
if (goog.isDef(anchoredElementOptions.element)) {
|
||||
this.setElement(anchoredElementOptions.element);
|
||||
}
|
||||
if (goog.isDef(anchoredElementOptions.position)) {
|
||||
this.setPosition(anchoredElementOptions.position);
|
||||
}
|
||||
if (goog.isDef(anchoredElementOptions.positioning)) {
|
||||
this.setPositioning(anchoredElementOptions.positioning);
|
||||
}
|
||||
if (goog.isDef(anchoredElementOptions.map)) {
|
||||
this.setMap(anchoredElementOptions.map);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.AnchoredElement, ol.Object);
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element|undefined} Element.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.getElement = function() {
|
||||
return /** @type {Element|undefined} */ (
|
||||
this.get(ol.AnchoredElementProperty.ELEMENT));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'getElement',
|
||||
ol.AnchoredElement.prototype.getElement);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map|undefined} Map.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.getMap = function() {
|
||||
return /** @type {ol.Map|undefined} */ (
|
||||
this.get(ol.AnchoredElementProperty.MAP));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'getMap',
|
||||
ol.AnchoredElement.prototype.getMap);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate|undefined} Position.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.getPosition = function() {
|
||||
return /** @type {ol.Coordinate|undefined} */ (
|
||||
this.get(ol.AnchoredElementProperty.POSITION));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'getPosition',
|
||||
ol.AnchoredElement.prototype.getPosition);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.AnchoredElementPositioning|undefined} Positioning.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.getPositioning = function() {
|
||||
return /** @type {ol.AnchoredElementPositioning|undefined} */ (
|
||||
this.get(ol.AnchoredElementProperty.POSITIONING));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'getPositioning',
|
||||
ol.AnchoredElement.prototype.getPositioning);
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.AnchoredElement.prototype.handleElementChanged = function() {
|
||||
goog.dom.removeChildren(this.element_);
|
||||
var element = this.getElement();
|
||||
if (goog.isDefAndNotNull(element)) {
|
||||
goog.dom.append(/** @type {!Node} */ (this.element_), element);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.AnchoredElement.prototype.handleMapChanged = function() {
|
||||
if (!goog.isNull(this.mapPostrenderListenerKey_)) {
|
||||
goog.dom.removeNode(this.element_);
|
||||
goog.events.unlistenByKey(this.mapPostrenderListenerKey_);
|
||||
this.mapPostrenderListenerKey_ = null;
|
||||
}
|
||||
var map = this.getMap();
|
||||
if (goog.isDefAndNotNull(map)) {
|
||||
this.mapPostrenderListenerKey_ = goog.events.listen(map,
|
||||
ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this);
|
||||
this.updatePixelPosition_();
|
||||
goog.dom.append(
|
||||
/** @type {!Node} */ (map.getOverlayContainer()), this.element_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.AnchoredElement.prototype.handleMapPostrender = function() {
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.AnchoredElement.prototype.handlePositionChanged = function() {
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.AnchoredElement.prototype.handlePositioningChanged = function() {
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element|undefined} element Element.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.setElement = function(element) {
|
||||
this.set(ol.AnchoredElementProperty.ELEMENT, element);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'setElement',
|
||||
ol.AnchoredElement.prototype.setElement);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map|undefined} map Map.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.setMap = function(map) {
|
||||
this.set(ol.AnchoredElementProperty.MAP, map);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'setMap',
|
||||
ol.AnchoredElement.prototype.setMap);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate|undefined} position Position.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.setPosition = function(position) {
|
||||
this.set(ol.AnchoredElementProperty.POSITION, position);
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.AnchoredElement.prototype,
|
||||
'setPosition',
|
||||
ol.AnchoredElement.prototype.setPosition);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.AnchoredElementPositioning|undefined} positioning Positioning.
|
||||
*/
|
||||
ol.AnchoredElement.prototype.setPositioning = function(positioning) {
|
||||
this.set(ol.AnchoredElementProperty.POSITIONING, positioning);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.AnchoredElement.prototype.updatePixelPosition_ = function() {
|
||||
|
||||
var map = this.getMap();
|
||||
var position = this.getPosition();
|
||||
if (!goog.isDef(map) || !map.isDef() || !goog.isDef(position)) {
|
||||
if (this.rendered_.visible) {
|
||||
goog.style.showElement(this.element_, false);
|
||||
this.rendered_.visible = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var pixel = map.getPixelFromCoordinate(position);
|
||||
var mapSize = map.getSize();
|
||||
goog.asserts.assert(goog.isDef(mapSize));
|
||||
var style = this.element_.style;
|
||||
var positioning = this.getPositioning();
|
||||
if (positioning == ol.AnchoredElementPositioning.BOTTOM_RIGHT ||
|
||||
positioning == ol.AnchoredElementPositioning.TOP_RIGHT) {
|
||||
if (this.rendered_.left_ !== '') {
|
||||
this.rendered_.left_ = style.left = '';
|
||||
}
|
||||
var right = Math.round(mapSize.width - pixel.x) + 'px';
|
||||
if (this.rendered_.right_ != right) {
|
||||
this.rendered_.right_ = style.right = right;
|
||||
}
|
||||
} else {
|
||||
if (this.rendered_.right_ !== '') {
|
||||
this.rendered_.right_ = style.right = '';
|
||||
}
|
||||
var left = Math.round(pixel.x) + 'px';
|
||||
if (this.rendered_.left_ != left) {
|
||||
this.rendered_.left_ = style.left = left;
|
||||
}
|
||||
}
|
||||
if (positioning == ol.AnchoredElementPositioning.TOP_LEFT ||
|
||||
positioning == ol.AnchoredElementPositioning.TOP_RIGHT) {
|
||||
if (this.rendered_.bottom_ !== '') {
|
||||
this.rendered_.bottom_ = style.bottom = '';
|
||||
}
|
||||
var top = Math.round(pixel.y) + 'px';
|
||||
if (this.rendered_.top_ != top) {
|
||||
this.rendered_.top_ = style.top = top;
|
||||
}
|
||||
} else {
|
||||
if (this.rendered_.top_ !== '') {
|
||||
this.rendered_.top_ = style.top = '';
|
||||
}
|
||||
var bottom = Math.round(mapSize.height - pixel.y) + 'px';
|
||||
if (this.rendered_.bottom_ != bottom) {
|
||||
this.rendered_.bottom_ = style.bottom = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.rendered_.visible) {
|
||||
goog.style.showElement(this.element_, true);
|
||||
this.rendered_.visible = true;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -9,25 +9,22 @@ goog.require('ol.easing');
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number=} opt_duration Duration.
|
||||
* @param {number=} opt_start Start.
|
||||
* @param {function(number): number=} opt_easingFunction Easing function.
|
||||
* @param {ol.animation.BounceOptions} options Options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
*/
|
||||
ol.animation.createBounce =
|
||||
function(resolution, opt_duration, opt_start, opt_easingFunction) {
|
||||
var start = goog.isDef(opt_start) ? opt_start : Date.now();
|
||||
var duration = goog.isDef(opt_duration) ? opt_duration : 1000;
|
||||
var easingFunction = goog.isDef(opt_easingFunction) ?
|
||||
opt_easingFunction : ol.easing.upAndDown;
|
||||
ol.animation.createBounce = function(options) {
|
||||
var resolution = options.resolution;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.upAndDown;
|
||||
return function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = easingFunction((frameState.time - start) / duration);
|
||||
var delta = easing((frameState.time - start) / duration);
|
||||
var deltaResolution = resolution - frameState.view2DState.resolution;
|
||||
frameState.animate = true;
|
||||
frameState.view2DState.resolution += delta * deltaResolution;
|
||||
@@ -41,27 +38,24 @@ ol.animation.createBounce =
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} source Source.
|
||||
* @param {number=} opt_duration Duration.
|
||||
* @param {number=} opt_start Start.
|
||||
* @param {function(number): number=} opt_easingFunction Easing function.
|
||||
* @param {ol.animation.PanFromOptions} options Options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
*/
|
||||
ol.animation.createPanFrom =
|
||||
function(source, opt_duration, opt_start, opt_easingFunction) {
|
||||
var start = goog.isDef(opt_start) ? opt_start : Date.now();
|
||||
ol.animation.createPanFrom = function(options) {
|
||||
var source = options.source;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var sourceX = source.x;
|
||||
var sourceY = source.y;
|
||||
var duration = goog.isDef(opt_duration) ? opt_duration : 1000;
|
||||
var easingFunction = goog.isDef(opt_easingFunction) ?
|
||||
opt_easingFunction : goog.fx.easing.inAndOut;
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : goog.fx.easing.inAndOut;
|
||||
return function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = 1 - easingFunction((frameState.time - start) / duration);
|
||||
var delta = 1 - easing((frameState.time - start) / duration);
|
||||
var deltaX = sourceX - frameState.view2DState.center.x;
|
||||
var deltaY = sourceY - frameState.view2DState.center.y;
|
||||
frameState.animate = true;
|
||||
@@ -77,27 +71,23 @@ ol.animation.createPanFrom =
|
||||
|
||||
|
||||
/**
|
||||
* @param {number=} opt_duration Duration.
|
||||
* @param {number=} opt_turns Turns.
|
||||
* @param {number=} opt_start Start.
|
||||
* @param {function(number): number=} opt_easingFunction Easing function.
|
||||
* @param {ol.animation.SpinOptions} options Options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
*/
|
||||
ol.animation.createSpin =
|
||||
function(opt_duration, opt_turns, opt_start, opt_easingFunction) {
|
||||
var start = goog.isDef(opt_start) ? opt_start : Date.now();
|
||||
var duration = goog.isDef(opt_duration) ? opt_duration : 1000;
|
||||
var turns = goog.isDef(opt_turns) ? opt_turns : 1;
|
||||
var deltaTheta = 2 * turns * Math.PI;
|
||||
var easingFunction = goog.isDef(opt_easingFunction) ?
|
||||
opt_easingFunction : goog.fx.easing.inAndOut;
|
||||
ol.animation.createSpin = function(options) {
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : goog.fx.easing.inAndOut;
|
||||
var deltaTheta = 2 * options.turns * Math.PI;
|
||||
|
||||
return function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = easingFunction((frameState.time - start) / duration);
|
||||
var delta = easing((frameState.time - start) / duration);
|
||||
frameState.animate = true;
|
||||
frameState.view2DState.rotation += delta * deltaTheta;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
@@ -110,25 +100,22 @@ ol.animation.createSpin =
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} sourceResolution Source resolution.
|
||||
* @param {number=} opt_duration Duration.
|
||||
* @param {number=} opt_start Start.
|
||||
* @param {function(number): number=} opt_easingFunction Easing function.
|
||||
* @param {ol.animation.ZoomFromOptions} options Options.
|
||||
* @return {ol.PreRenderFunction} Pre-render function.
|
||||
*/
|
||||
ol.animation.createZoomFrom =
|
||||
function(sourceResolution, opt_duration, opt_start, opt_easingFunction) {
|
||||
var start = goog.isDef(opt_start) ? opt_start : Date.now();
|
||||
var duration = goog.isDef(opt_duration) ? opt_duration : 1000;
|
||||
var easingFunction = goog.isDef(opt_easingFunction) ?
|
||||
opt_easingFunction : ol.easing.linear;
|
||||
ol.animation.createZoomFrom = function(options) {
|
||||
var sourceResolution = options.resolution;
|
||||
var start = goog.isDef(options.start) ? options.start : goog.now();
|
||||
var duration = goog.isDef(options.duration) ? options.duration : 1000;
|
||||
var easing = goog.isDef(options.easing) ?
|
||||
options.easing : ol.easing.linear;
|
||||
return function(map, frameState) {
|
||||
if (frameState.time < start) {
|
||||
frameState.animate = true;
|
||||
frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
|
||||
return true;
|
||||
} else if (frameState.time < start + duration) {
|
||||
var delta = 1 - easingFunction((frameState.time - start) / duration);
|
||||
var delta = 1 - easing((frameState.time - start) / duration);
|
||||
var deltaResolution =
|
||||
sourceResolution - frameState.view2DState.resolution;
|
||||
frameState.animate = true;
|
||||
|
||||
@@ -69,7 +69,7 @@ ol.control.Attribution.prototype.handleMapPostrender = function(mapEvent) {
|
||||
if (goog.isNull(frameState)) {
|
||||
this.updateElement_(null);
|
||||
} else {
|
||||
this.updateElement_(frameState.tileUsage);
|
||||
this.updateElement_(frameState.usedTiles);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,12 +94,12 @@ ol.control.Attribution.prototype.setMap = function(map) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {?Object.<string, Object.<string, ol.TileRange>>} tileUsage Tile
|
||||
* usage.
|
||||
* @param {?Object.<string, Object.<string, ol.TileRange>>} usedTiles Used
|
||||
* tiles.
|
||||
*/
|
||||
ol.control.Attribution.prototype.updateElement_ = function(tileUsage) {
|
||||
ol.control.Attribution.prototype.updateElement_ = function(usedTiles) {
|
||||
|
||||
if (goog.isNull(tileUsage)) {
|
||||
if (goog.isNull(usedTiles)) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.showElement(this.element, false);
|
||||
this.renderedVisible_ = false;
|
||||
@@ -136,14 +136,14 @@ ol.control.Attribution.prototype.updateElement_ = function(tileUsage) {
|
||||
var attributions = {};
|
||||
var i, tileRanges, tileSource, tileSourceAttribution,
|
||||
tileSourceAttributionKey, tileSourceAttributions, tileSourceKey, z;
|
||||
for (tileSourceKey in tileUsage) {
|
||||
for (tileSourceKey in usedTiles) {
|
||||
goog.asserts.assert(tileSourceKey in tileSources);
|
||||
tileSource = tileSources[tileSourceKey];
|
||||
tileSourceAttributions = tileSource.getAttributions();
|
||||
if (goog.isNull(tileSourceAttributions)) {
|
||||
continue;
|
||||
}
|
||||
tileRanges = tileUsage[tileSourceKey];
|
||||
tileRanges = usedTiles[tileSourceKey];
|
||||
for (i = 0; i < tileSourceAttributions.length; ++i) {
|
||||
tileSourceAttribution = tileSourceAttributions[i];
|
||||
tileSourceAttributionKey = goog.getUid(tileSourceAttribution).toString();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
goog.provide('ol.control.MousePosition');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
|
||||
@@ -21,3 +21,40 @@ ol.easing.upAndDown = function(t) {
|
||||
return 1 - goog.fx.easing.inAndOut(2 * (t - 0.5));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* from https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael.js
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
*/
|
||||
ol.easing.elastic = function(t) {
|
||||
return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* from https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael.js
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
*/
|
||||
ol.easing.bounce = function(t) {
|
||||
var s = 7.5625, p = 2.75, l;
|
||||
if (t < (1 / p)) {
|
||||
l = s * t * t;
|
||||
} else {
|
||||
if (t < (2 / p)) {
|
||||
t -= (1.5 / p);
|
||||
l = s * t * t + 0.75;
|
||||
} else {
|
||||
if (t < (2.5 / p)) {
|
||||
t -= (2.25 / p);
|
||||
l = s * t * t + 0.9375;
|
||||
} else {
|
||||
t -= (2.625 / p);
|
||||
l = s * t * t + 0.984375;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
@@ -94,7 +94,8 @@ ol.Extent.prototype.getTopRight = function() {
|
||||
* @return {ol.Extent} Extent.
|
||||
*/
|
||||
ol.Extent.prototype.transform = function(transformFn) {
|
||||
var min = transformFn(new ol.Coordinate(this.minX, this.minY));
|
||||
var max = transformFn(new ol.Coordinate(this.maxX, this.maxY));
|
||||
return new ol.Extent(min.x, min.y, max.x, max.y);
|
||||
var a = transformFn(new ol.Coordinate(this.minX, this.minY));
|
||||
var b = transformFn(new ol.Coordinate(this.maxX, this.maxY));
|
||||
return new ol.Extent(Math.min(a.x, b.x), Math.min(a.y, b.y),
|
||||
Math.max(a.x, b.x), Math.max(a.y, b.y));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// FIXME add view3DState
|
||||
// FIXME factor out common code between usedTiles and wantedTiles
|
||||
|
||||
goog.provide('ol.FrameState');
|
||||
goog.provide('ol.PostRenderFunction');
|
||||
@@ -26,10 +27,11 @@ goog.require('ol.layer.LayerState');
|
||||
* postRenderFunctions: Array.<ol.PostRenderFunction>,
|
||||
* size: ol.Size,
|
||||
* tileQueue: ol.TileQueue,
|
||||
* tileUsage: Object.<string, Object.<string, ol.TileRange>>,
|
||||
* time: number,
|
||||
* usedTiles: Object.<string, Object.<string, ol.TileRange>>,
|
||||
* view2DState: ol.View2DState,
|
||||
* viewHints: Array.<number>}}
|
||||
* viewHints: Array.<number>,
|
||||
* wantedTiles: Object.<string, Object.<string, ol.TileRange>>}}
|
||||
*/
|
||||
ol.FrameState;
|
||||
|
||||
|
||||
@@ -20,6 +20,18 @@ ol.interaction.condition.altKeyOnly = function(browserEvent) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @return {boolean} True if only the alt and shift keys are pressed.
|
||||
*/
|
||||
ol.interaction.condition.altShiftKeysOnly = function(browserEvent) {
|
||||
return (
|
||||
browserEvent.altKey &&
|
||||
!browserEvent.platformModifierKey &&
|
||||
browserEvent.shiftKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @return {boolean} True if only the no modifier keys are pressed.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
@exportClass ol.Map ol.MapOptions
|
||||
@exportProperty ol.Map.prototype.addPreRenderFunction
|
||||
@exportProperty ol.Map.prototype.addPreRenderFunctions
|
||||
@exportProperty ol.Map.prototype.getControls
|
||||
@exportProperty ol.Map.prototype.getInteractions
|
||||
|
||||
|
||||
139
src/ol/map.js
139
src/ol/map.js
@@ -8,7 +8,6 @@ goog.provide('ol.RendererHint');
|
||||
goog.provide('ol.RendererHints');
|
||||
|
||||
goog.require('goog.Uri.QueryData');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.async.AnimationDelay');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dispose');
|
||||
@@ -175,6 +174,12 @@ ol.Map = function(mapOptions) {
|
||||
*/
|
||||
this.target_ = mapOptionsInternal.target;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?number}
|
||||
*/
|
||||
this.viewPropertyListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
@@ -278,8 +283,16 @@ ol.Map = function(mapOptions) {
|
||||
*/
|
||||
this.tileQueue_ = new ol.TileQueue(goog.bind(this.getTilePriority, this));
|
||||
|
||||
goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.VIEW),
|
||||
this.handleViewChanged_, false, this);
|
||||
goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
|
||||
this.handleSizeChanged_, false, this);
|
||||
goog.events.listen(
|
||||
this, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR),
|
||||
this.handleBackgroundColorChanged_, false, this),
|
||||
this.setValues(mapOptionsInternal.values);
|
||||
|
||||
// this gives the map an initial size
|
||||
this.handleBrowserWindowResize();
|
||||
|
||||
this.controls_.forEach(
|
||||
@@ -345,6 +358,14 @@ goog.exportProperty(
|
||||
ol.Map.prototype.getBackgroundColor);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.renderer.Map} Renderer.
|
||||
*/
|
||||
ol.Map.prototype.getRenderer = function() {
|
||||
return this.renderer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Container.
|
||||
*/
|
||||
@@ -391,6 +412,10 @@ ol.Map.prototype.getInteractions = function() {
|
||||
ol.Map.prototype.getLayers = function() {
|
||||
return /** @type {ol.Collection} */ (this.get(ol.MapProperty.LAYERS));
|
||||
};
|
||||
goog.exportProperty(
|
||||
ol.Map.prototype,
|
||||
'getLayers',
|
||||
ol.Map.prototype.getLayers);
|
||||
|
||||
|
||||
/**
|
||||
@@ -453,19 +478,24 @@ ol.Map.prototype.getOverlayContainer = function() {
|
||||
|
||||
/**
|
||||
* @param {ol.Tile} tile Tile.
|
||||
* @param {string} tileSourceKey Tile source key.
|
||||
* @param {ol.Coordinate} tileCenter Tile center.
|
||||
* @param {number} tileResolution Tile resolution.
|
||||
* @return {number|undefined} Tile priority.
|
||||
* @return {number} Tile priority.
|
||||
*/
|
||||
ol.Map.prototype.getTilePriority = function(tile, tileCenter, tileResolution) {
|
||||
if (goog.isNull(this.frameState_)) {
|
||||
return undefined;
|
||||
} else {
|
||||
var center = this.frameState_.view2DState.center;
|
||||
ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter) {
|
||||
var frameState = this.frameState_;
|
||||
if (goog.isNull(frameState) || !(tileSourceKey in frameState.wantedTiles)) {
|
||||
return ol.TileQueue.DROP;
|
||||
}
|
||||
var zKey = tile.tileCoord.z.toString();
|
||||
if (!(zKey in frameState.wantedTiles[tileSourceKey]) ||
|
||||
!frameState.wantedTiles[tileSourceKey][zKey].contains(tile.tileCoord)) {
|
||||
return ol.TileQueue.DROP;
|
||||
}
|
||||
var center = frameState.view2DState.center;
|
||||
var deltaX = tileCenter.x - center.x;
|
||||
var deltaY = tileCenter.y - center.y;
|
||||
return Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
|
||||
}
|
||||
return deltaX * deltaX + deltaY * deltaY;
|
||||
};
|
||||
|
||||
|
||||
@@ -525,13 +555,20 @@ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) {
|
||||
ol.Map.prototype.handlePostRender = function() {
|
||||
this.tileQueue_.reprioritize(); // FIXME only call if needed
|
||||
this.tileQueue_.loadMoreTiles();
|
||||
goog.array.forEach(
|
||||
this.postRenderFunctions_,
|
||||
function(postRenderFunction) {
|
||||
postRenderFunction(this, this.frameState_);
|
||||
},
|
||||
this);
|
||||
this.postRenderFunctions_.length = 0;
|
||||
var postRenderFunctions = this.postRenderFunctions_;
|
||||
var i;
|
||||
for (i = 0; i < postRenderFunctions.length; ++i) {
|
||||
postRenderFunctions[i](this, this.frameState_);
|
||||
}
|
||||
postRenderFunctions.length = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.handleBackgroundColorChanged_ = function() {
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
@@ -544,6 +581,40 @@ ol.Map.prototype.handleBrowserWindowResize = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.handleSizeChanged_ = function() {
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.handleViewPropertyChanged_ = function() {
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.handleViewChanged_ = function() {
|
||||
if (!goog.isNull(this.viewPropertyListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.viewPropertyListenerKey_);
|
||||
this.viewPropertyListenerKey_ = null;
|
||||
}
|
||||
var view = this.getView();
|
||||
if (goog.isDefAndNotNull(view)) {
|
||||
this.viewPropertyListenerKey_ = goog.events.listen(
|
||||
view, ol.ObjectEventType.CHANGED,
|
||||
this.handleViewPropertyChanged_, false, this);
|
||||
}
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is defined.
|
||||
*/
|
||||
@@ -611,9 +682,11 @@ ol.Map.prototype.renderFrame_ = function(time) {
|
||||
var backgroundColor = this.getBackgroundColor();
|
||||
var viewHints = view.getHints();
|
||||
var layerStates = {};
|
||||
goog.array.forEach(layersArray, function(layer) {
|
||||
var layer;
|
||||
for (i = 0; i < layersArray.length; ++i) {
|
||||
layer = layersArray[i];
|
||||
layerStates[goog.getUid(layer)] = layer.getLayerState();
|
||||
});
|
||||
}
|
||||
var view2DState = view2D.getView2DState();
|
||||
frameState = {
|
||||
animate: false,
|
||||
@@ -627,19 +700,23 @@ ol.Map.prototype.renderFrame_ = function(time) {
|
||||
postRenderFunctions: [],
|
||||
size: size,
|
||||
tileQueue: this.tileQueue_,
|
||||
tileUsage: {},
|
||||
time: time,
|
||||
usedTiles: {},
|
||||
view2DState: view2DState,
|
||||
viewHints: viewHints,
|
||||
time: time
|
||||
wantedTiles: {}
|
||||
};
|
||||
}
|
||||
|
||||
this.preRenderFunctions_ = goog.array.filter(
|
||||
this.preRenderFunctions_,
|
||||
function(preRenderFunction) {
|
||||
return preRenderFunction(this, frameState);
|
||||
},
|
||||
this);
|
||||
var preRenderFunctions = this.preRenderFunctions_;
|
||||
var n = 0, preRenderFunction;
|
||||
for (i = 0; i < preRenderFunctions.length; ++i) {
|
||||
preRenderFunction = preRenderFunctions[i];
|
||||
if (preRenderFunction(this, frameState)) {
|
||||
preRenderFunctions[n++] = preRenderFunction;
|
||||
}
|
||||
}
|
||||
preRenderFunctions.length = n;
|
||||
|
||||
if (!goog.isNull(frameState)) {
|
||||
// FIXME works for View2D only
|
||||
@@ -664,6 +741,8 @@ ol.Map.prototype.renderFrame_ = function(time) {
|
||||
}
|
||||
|
||||
this.renderer_.renderFrame(frameState);
|
||||
this.frameState_ = frameState;
|
||||
this.dirty_ = false;
|
||||
|
||||
if (!goog.isNull(frameState)) {
|
||||
if (frameState.animate) {
|
||||
@@ -672,8 +751,6 @@ ol.Map.prototype.renderFrame_ = function(time) {
|
||||
Array.prototype.push.apply(
|
||||
this.postRenderFunctions_, frameState.postRenderFunctions);
|
||||
}
|
||||
this.frameState_ = frameState;
|
||||
this.dirty_ = false;
|
||||
|
||||
this.dispatchEvent(
|
||||
new ol.MapEvent(ol.MapEventType.POSTRENDER, this, frameState));
|
||||
@@ -893,8 +970,8 @@ ol.Map.createInteractions_ = function(mapOptions) {
|
||||
var rotate = goog.isDef(mapOptions.rotate) ?
|
||||
mapOptions.rotate : true;
|
||||
if (rotate) {
|
||||
interactions.push(
|
||||
new ol.interaction.DragRotate(ol.interaction.condition.altKeyOnly));
|
||||
interactions.push(new ol.interaction.DragRotate(
|
||||
ol.interaction.condition.altShiftKeysOnly));
|
||||
}
|
||||
|
||||
var doubleClickZoom = goog.isDef(mapOptions.doubleClickZoom) ?
|
||||
|
||||
@@ -2,6 +2,7 @@ goog.provide('ol.MapBrowserEvent');
|
||||
goog.provide('ol.MapBrowserEvent.EventType');
|
||||
goog.provide('ol.MapBrowserEventHandler');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@exportClass ol.overlay.Overlay ol.overlay.OverlayOptions
|
||||
@exportProperty ol.overlay.Overlay.prototype.getElement
|
||||
@exportProperty ol.overlay.Overlay.prototype.setCoordinate
|
||||
@exportProperty ol.overlay.Overlay.prototype.setMap
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
goog.provide('ol.overlay.Overlay');
|
||||
goog.provide('ol.overlay.OverlayPositioning');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.overlay.OverlayOptions} overlayOptions Overlay options.
|
||||
*/
|
||||
ol.overlay.Overlay = function(overlayOptions) {
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.coordinate_ = null;
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.element_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
this.positioning_ = [
|
||||
ol.overlay.OverlayPositioning.LEFT,
|
||||
ol.overlay.OverlayPositioning.BOTTOM
|
||||
];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.mapListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.viewListenerKeys_ = null;
|
||||
|
||||
if (goog.isDef(overlayOptions.coordinate)) {
|
||||
this.setCoordinate(overlayOptions.coordinate);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.element)) {
|
||||
this.setElement(overlayOptions.element);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.map)) {
|
||||
this.setMap(overlayOptions.map);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.positioning)) {
|
||||
this.setPositioning(overlayOptions.positioning);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setCoordinate = function(coordinate) {
|
||||
this.coordinate_ = coordinate;
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} element The DOM element for the overlay.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setElement = function(element) {
|
||||
if (this.element_) {
|
||||
goog.dom.removeNode(this.element_);
|
||||
}
|
||||
this.element_ = element;
|
||||
if (this.map_) {
|
||||
goog.style.setStyle(this.element_, 'position', 'absolute');
|
||||
goog.dom.append(/** @type {!Node} */ (this.map_.getOverlayContainer()),
|
||||
this.element_);
|
||||
}
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} The DOM element for the overlay.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.getElement = function() {
|
||||
return this.element_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setMap = function(map) {
|
||||
this.map_ = map;
|
||||
if (!goog.isNull(this.mapListenerKeys_)) {
|
||||
goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
|
||||
this.mapListenerKeys_ = null;
|
||||
}
|
||||
if (this.element_) {
|
||||
this.setElement(this.element_);
|
||||
}
|
||||
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_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the CSS properties to use for x- and y-positioning of the element. If
|
||||
* not set, the default is {@code ['left', 'bottom']}.
|
||||
* @param {Array.<string>} positioning The positioning.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setPositioning = function(positioning) {
|
||||
this.positioning_ = positioning;
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.updatePixelPosition_ = function() {
|
||||
if (!goog.isNull(this.map_) && !goog.isNull(this.coordinate_) &&
|
||||
!goog.isNull(this.element_)) {
|
||||
var pixel = this.map_.getPixelFromCoordinate(this.coordinate_);
|
||||
var mapSize = this.map_.get(ol.MapProperty.SIZE);
|
||||
var x = Math.round(pixel.x);
|
||||
if (this.positioning_[0] === ol.overlay.OverlayPositioning.RIGHT) {
|
||||
x = mapSize.width - x;
|
||||
}
|
||||
var y = Math.round(pixel.y);
|
||||
if (this.positioning_[1] === ol.overlay.OverlayPositioning.BOTTOM) {
|
||||
y = mapSize.height - y;
|
||||
}
|
||||
goog.style.setStyle(this.element_, this.positioning_[0], x + 'px');
|
||||
goog.style.setStyle(this.element_, this.positioning_[1], y + 'px');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.overlay.OverlayPositioning = {
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
TOP: 'top',
|
||||
BOTTOM: 'bottom'
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
goog.provide('ol.renderer.canvas.Map');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.vec.Mat4');
|
||||
@@ -73,44 +74,8 @@ ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.handleBackgroundColorChanged = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.handleViewPropertyChanged = function() {
|
||||
goog.base(this, 'handleViewPropertyChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.handleLayerRendererChange = function(event) {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.handleSizeChanged = function() {
|
||||
goog.base(this, 'handleSizeChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.handleViewChanged = function() {
|
||||
goog.base(this, 'handleViewChanged');
|
||||
this.getMap().render();
|
||||
ol.renderer.canvas.Map.prototype.getCanvas = function() {
|
||||
return this.canvas_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
goog.provide('ol.renderer.canvas.TileLayer');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.vec.Mat4');
|
||||
@@ -87,6 +88,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
|
||||
|
||||
var tileLayer = this.getTileLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileSourceKey = goog.getUid(tileSource).toString();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var tileSize = tileGrid.getTileSize();
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
@@ -165,7 +167,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
|
||||
frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter);
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
continue;
|
||||
@@ -213,9 +215,11 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
|
||||
|
||||
if (!allTilesLoaded) {
|
||||
frameState.animate = true;
|
||||
this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange);
|
||||
}
|
||||
|
||||
this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
|
||||
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
|
||||
this.scheduleExpireCache(frameState, tileSource);
|
||||
|
||||
var transform = this.transform_;
|
||||
goog.vec.Mat4.makeIdentity(transform);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
goog.provide('ol.renderer.dom.Map');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
|
||||
@@ -83,6 +83,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
|
||||
|
||||
var tileLayer = this.getTileLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileSourceKey = goog.getUid(tileSource).toString();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
@@ -132,7 +133,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
|
||||
frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter);
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
continue;
|
||||
@@ -234,9 +235,11 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
|
||||
|
||||
if (!allTilesLoaded) {
|
||||
frameState.animate = true;
|
||||
this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange);
|
||||
}
|
||||
|
||||
this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
|
||||
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
|
||||
this.scheduleExpireCache(frameState, tileSource);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@ goog.provide('ol.renderer.Layer');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.Object');
|
||||
goog.require('ol.TileRange');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.LayerProperty');
|
||||
goog.require('ol.source.TileSource');
|
||||
|
||||
|
||||
|
||||
@@ -130,24 +132,66 @@ ol.renderer.Layer.prototype.handleLayerVisibleChange = goog.nullFunction;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {Object.<string, Object.<string, ol.TileRange>>} tileUsage Tile usage.
|
||||
* @param {ol.FrameState} frameState Frame state.
|
||||
* @param {ol.source.TileSource} tileSource Tile source.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.scheduleExpireCache =
|
||||
function(frameState, tileSource) {
|
||||
if (tileSource.canExpireCache()) {
|
||||
frameState.postRenderFunctions.push(
|
||||
goog.partial(function(tileSource, map, frameState) {
|
||||
var tileSourceKey = goog.getUid(tileSource).toString();
|
||||
tileSource.expireCache(frameState.usedTiles[tileSourceKey]);
|
||||
}, tileSource));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {Object.<string, Object.<string, ol.TileRange>>} usedTiles Used tiles.
|
||||
* @param {ol.source.Source} source Source.
|
||||
* @param {number} z Z.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.updateTileUsage =
|
||||
function(tileUsage, source, z, tileRange) {
|
||||
ol.renderer.Layer.prototype.updateUsedTiles =
|
||||
function(usedTiles, source, z, tileRange) {
|
||||
// FIXME should we use tilesToDrawByZ instead?
|
||||
var sourceKey = goog.getUid(source).toString();
|
||||
var zKey = z.toString();
|
||||
if (sourceKey in tileUsage) {
|
||||
if (z in tileUsage[sourceKey]) {
|
||||
tileUsage[sourceKey][zKey].extend(tileRange);
|
||||
if (sourceKey in usedTiles) {
|
||||
if (zKey in usedTiles[sourceKey]) {
|
||||
usedTiles[sourceKey][zKey].extend(tileRange);
|
||||
} else {
|
||||
tileUsage[sourceKey][zKey] = tileRange;
|
||||
usedTiles[sourceKey][zKey] = tileRange;
|
||||
}
|
||||
} else {
|
||||
tileUsage[sourceKey] = {};
|
||||
tileUsage[sourceKey][zKey] = tileRange;
|
||||
usedTiles[sourceKey] = {};
|
||||
usedTiles[sourceKey][zKey] = tileRange;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {Object.<string, Object.<string, ol.TileRange>>} wantedTiles Wanted
|
||||
* tile ranges.
|
||||
* @param {ol.source.Source} source Source.
|
||||
* @param {number} z Z.
|
||||
* @param {ol.TileRange} tileRange Tile range.
|
||||
*/
|
||||
ol.renderer.Layer.prototype.updateWantedTiles =
|
||||
function(wantedTiles, source, z, tileRange) {
|
||||
var sourceKey = goog.getUid(source).toString();
|
||||
var zKey = z.toString();
|
||||
if (sourceKey in wantedTiles) {
|
||||
if (zKey in wantedTiles[sourceKey]) {
|
||||
wantedTiles[sourceKey][zKey].extend(tileRange);
|
||||
} else {
|
||||
wantedTiles[sourceKey][zKey] = tileRange;
|
||||
}
|
||||
} else {
|
||||
wantedTiles[sourceKey] = {};
|
||||
wantedTiles[sourceKey][zKey] = tileRange;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
goog.provide('ol.renderer.Map');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.array');
|
||||
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.FrameState');
|
||||
goog.require('ol.View2D');
|
||||
@@ -41,40 +40,24 @@ ol.renderer.Map = function(container, map) {
|
||||
*/
|
||||
this.layerRenderers = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.layersListenerKeys_ = null;
|
||||
|
||||
//
|
||||
// We listen to layer add/remove to add/remove layer renderers.
|
||||
//
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?number}
|
||||
*/
|
||||
this.viewPropertyListenerKey_ = null;
|
||||
this.mapLayersChangedListenerKey_ =
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS),
|
||||
this.handleLayersChanged, false, this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.mapListenerKeys_ = [
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR),
|
||||
this.handleBackgroundColorChanged, 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.SIZE),
|
||||
this.handleSizeChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.VIEW),
|
||||
this.handleViewChanged, false, this)
|
||||
];
|
||||
this.layersListenerKeys_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.Map, goog.Disposable);
|
||||
@@ -137,10 +120,7 @@ ol.renderer.Map.prototype.disposeInternal = function() {
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
goog.dispose(layerRenderer);
|
||||
});
|
||||
goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
|
||||
if (!goog.isNull(this.viewPropertyListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.viewPropertyListenerKey_);
|
||||
}
|
||||
goog.events.unlistenByKey(this.mapLayersChangedListenerKey_);
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
}
|
||||
@@ -148,6 +128,12 @@ ol.renderer.Map.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Canvas.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getCanvas = goog.functions.NULL;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @protected
|
||||
@@ -169,12 +155,6 @@ ol.renderer.Map.prototype.getMap = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle background color changed.
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleBackgroundColorChanged = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
@@ -218,40 +198,6 @@ ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleViewPropertyChanged = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleSizeChanged = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @protected
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// FIXME clear textureCache
|
||||
// FIXME generational tile texture garbage collector newFrame/get
|
||||
// FIXME check against gl.getParameter(webgl.MAX_TEXTURE_SIZE)
|
||||
|
||||
goog.provide('ol.renderer.webgl.Map');
|
||||
goog.provide('ol.renderer.webgl.map.shader');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dispose');
|
||||
goog.require('goog.dom');
|
||||
@@ -17,13 +16,21 @@ goog.require('goog.webgl');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.TileLayer');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.webgl.FragmentShader');
|
||||
goog.require('ol.renderer.webgl.TileLayer');
|
||||
goog.require('ol.renderer.webgl.VertexShader');
|
||||
goog.require('ol.structs.LinkedMap');
|
||||
goog.require('ol.webgl');
|
||||
goog.require('ol.webgl.WebGLContextEventType');
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} Texture cache high water mark.
|
||||
*/
|
||||
ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{magFilter: number, minFilter: number, texture: WebGLTexture}}
|
||||
*/
|
||||
@@ -177,9 +184,15 @@ ol.renderer.webgl.Map = function(container, map) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.renderer.webgl.TextureCacheEntry>}
|
||||
* @type {ol.structs.LinkedMap}
|
||||
*/
|
||||
this.textureCache_ = {};
|
||||
this.textureCache_ = new ol.structs.LinkedMap(undefined, true);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.textureCacheFrameMarkerCount_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -225,8 +238,8 @@ ol.renderer.webgl.Map.prototype.bindTileTexture =
|
||||
function(tile, magFilter, minFilter) {
|
||||
var gl = this.getGL();
|
||||
var tileKey = tile.getKey();
|
||||
var textureCacheEntry = this.textureCache_[tileKey];
|
||||
if (goog.isDef(textureCacheEntry)) {
|
||||
if (this.textureCache_.containsKey(tileKey)) {
|
||||
var textureCacheEntry = this.textureCache_.get(tileKey);
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, textureCacheEntry.texture);
|
||||
if (textureCacheEntry.magFilter != magFilter) {
|
||||
gl.texParameteri(
|
||||
@@ -251,11 +264,11 @@ ol.renderer.webgl.Map.prototype.bindTileTexture =
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_T,
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
this.textureCache_[tileKey] = {
|
||||
this.textureCache_.set(tileKey, {
|
||||
texture: texture,
|
||||
magFilter: magFilter,
|
||||
minFilter: minFilter
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -285,14 +298,50 @@ ol.renderer.webgl.Map.prototype.disposeInternal = function() {
|
||||
goog.object.forEach(this.shaderCache_, function(shader) {
|
||||
gl.deleteShader(shader);
|
||||
});
|
||||
goog.object.forEach(this.textureCache_, function(textureCacheEntry) {
|
||||
this.textureCache_.forEach(function(textureCacheEntry) {
|
||||
if (!goog.isNull(textureCacheEntry)) {
|
||||
gl.deleteTexture(textureCacheEntry.texture);
|
||||
}
|
||||
});
|
||||
}
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {ol.FrameState} frameState Frame state.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.expireCache_ = function(map, frameState) {
|
||||
var gl = this.getGL();
|
||||
var key, textureCacheEntry;
|
||||
while (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ >
|
||||
ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) {
|
||||
textureCacheEntry = /** @type {?ol.renderer.webgl.TextureCacheEntry} */
|
||||
(this.textureCache_.peekLast());
|
||||
if (goog.isNull(textureCacheEntry)) {
|
||||
if (+this.textureCache_.peekLastKey() == frameState.time) {
|
||||
break;
|
||||
} else {
|
||||
--this.textureCacheFrameMarkerCount_;
|
||||
}
|
||||
} else {
|
||||
gl.deleteTexture(textureCacheEntry.texture);
|
||||
}
|
||||
this.textureCache_.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.getCanvas = function() {
|
||||
return this.canvas_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {WebGLRenderingContext} GL.
|
||||
*/
|
||||
@@ -360,14 +409,6 @@ ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
@@ -390,7 +431,8 @@ ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) {
|
||||
this.arrayBuffer_ = null;
|
||||
this.shaderCache_ = {};
|
||||
this.programCache_ = {};
|
||||
this.textureCache_ = {};
|
||||
this.textureCache_.clear();
|
||||
this.textureCacheFrameMarkerCount_ = 0;
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
layerRenderer.handleWebGLContextLost();
|
||||
});
|
||||
@@ -427,7 +469,7 @@ ol.renderer.webgl.Map.prototype.initializeGL_ = function() {
|
||||
* @return {boolean} Is tile texture loaded.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.isTileTextureLoaded = function(tile) {
|
||||
return tile.getKey() in this.textureCache_;
|
||||
return this.textureCache_.containsKey(tile.getKey());
|
||||
};
|
||||
|
||||
|
||||
@@ -471,6 +513,9 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.textureCache_.set(frameState.time.toString(), null);
|
||||
++this.textureCacheFrameMarkerCount_;
|
||||
|
||||
goog.array.forEach(frameState.layersArray, function(layer) {
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
if (!layerState.visible || !layerState.ready) {
|
||||
@@ -553,6 +598,11 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
|
||||
this.calculateMatrices2D(frameState);
|
||||
|
||||
if (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ >
|
||||
ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) {
|
||||
frameState.postRenderFunctions.push(goog.bind(this.expireCache_, this));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
|
||||
|
||||
var tileLayer = this.getTileLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileSourceKey = goog.getUid(tileSource).toString();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
@@ -392,7 +393,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
|
||||
frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter);
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
if (mapRenderer.isTileTextureLoaded(tile)) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
@@ -455,11 +456,13 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
|
||||
this.renderedTileRange_ = null;
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
frameState.animate = true;
|
||||
this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
|
||||
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
|
||||
this.scheduleExpireCache(frameState, tileSource);
|
||||
|
||||
goog.vec.Mat4.makeIdentity(this.matrix_);
|
||||
goog.vec.Mat4.translate(this.matrix_,
|
||||
|
||||
@@ -2,6 +2,7 @@ goog.provide('ol.BingMapsStyle');
|
||||
goog.provide('ol.source.BingMaps');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.net.Jsonp');
|
||||
|
||||
1
src/ol/source/debugtilesource.exports
Normal file
1
src/ol/source/debugtilesource.exports
Normal file
@@ -0,0 +1 @@
|
||||
@exportClass ol.source.DebugTileSource ol.source.DebugTileSourceOptions
|
||||
@@ -1,8 +1,8 @@
|
||||
goog.provide('ol.source.DebugTileSource');
|
||||
goog.provide('ol.source.DebugTileSourceOptions');
|
||||
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.source.TileSource');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
@@ -79,14 +79,6 @@ ol.DebugTile_.prototype.getImage = function(opt_context) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{extent: (ol.Extent|undefined),
|
||||
* projection: (ol.Projection|undefined),
|
||||
* tileGrid: (ol.tilegrid.TileGrid|undefined)}}
|
||||
*/
|
||||
ol.source.DebugTileSourceOptions;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
@@ -103,26 +95,40 @@ ol.source.DebugTileSource = function(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.DebugTile_>}
|
||||
* FIXME will need to expire elements from this cache
|
||||
* FIXME see elemoine's work with goog.structs.LinkedMap
|
||||
* @type {ol.TileCache}
|
||||
*/
|
||||
this.tileCache_ = {};
|
||||
this.tileCache_ = new ol.TileCache();
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.DebugTileSource, ol.source.TileSource);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.DebugTileSource.prototype.canExpireCache = function() {
|
||||
return this.tileCache_.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.DebugTileSource.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache_.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.DebugTileSource.prototype.getTile = function(tileCoord) {
|
||||
var key = tileCoord.toString();
|
||||
if (goog.object.containsKey(this.tileCache_, key)) {
|
||||
return this.tileCache_[key];
|
||||
if (this.tileCache_.containsKey(key)) {
|
||||
return /** @type {ol.DebugTile_} */ (this.tileCache_.get(key));
|
||||
} else {
|
||||
var tile = new ol.DebugTile_(tileCoord, this.tileGrid);
|
||||
this.tileCache_[key] = tile;
|
||||
this.tileCache_.set(key, tile);
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ goog.require('ol.Attribution');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.ImageTile');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.TileCache');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileUrlFunction');
|
||||
goog.require('ol.TileUrlFunctionType');
|
||||
@@ -55,32 +56,46 @@ ol.source.ImageTileSource = function(options) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.ImageTile>}
|
||||
* FIXME will need to expire elements from this cache
|
||||
* FIXME see elemoine's work with goog.structs.LinkedMap
|
||||
* @type {ol.TileCache}
|
||||
*/
|
||||
this.tileCache_ = {};
|
||||
this.tileCache_ = new ol.TileCache();
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.ImageTileSource, ol.source.TileSource);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.ImageTileSource.prototype.canExpireCache = function() {
|
||||
return this.tileCache_.canExpireCache();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.ImageTileSource.prototype.expireCache = function(usedTiles) {
|
||||
this.tileCache_.expireCache(usedTiles);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.ImageTileSource.prototype.getTile = function(tileCoord) {
|
||||
var key = tileCoord.toString();
|
||||
if (goog.object.containsKey(this.tileCache_, key)) {
|
||||
return this.tileCache_[key];
|
||||
if (this.tileCache_.containsKey(key)) {
|
||||
return /** @type {ol.Tile} */ (this.tileCache_.get(key));
|
||||
} else {
|
||||
var tileUrl = this.getTileCoordUrl(tileCoord);
|
||||
var tile;
|
||||
if (goog.isDef(tileUrl)) {
|
||||
tile = new ol.ImageTile(tileCoord, tileUrl, this.crossOrigin_);
|
||||
this.tileCache_.set(key, tile);
|
||||
} else {
|
||||
tile = null;
|
||||
}
|
||||
this.tileCache_[key] = tile;
|
||||
return tile;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ goog.require('ol.TileUrlFunction');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{attribtions: (Array.<ol.Attribution>|undefined),
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* extent: (ol.Extent|undefined),
|
||||
* projection: (ol.Projection|undefined)}}
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
goog.provide('ol.source.TiledWMS');
|
||||
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.uri.utils');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
goog.provide('ol.source.TileSource');
|
||||
goog.provide('ol.source.TileSourceOptions');
|
||||
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Attribution');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Projection');
|
||||
@@ -46,6 +47,18 @@ ol.source.TileSource = function(tileSourceOptions) {
|
||||
goog.inherits(ol.source.TileSource, ol.source.Source);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can expire cache.
|
||||
*/
|
||||
ol.source.TileSource.prototype.canExpireCache = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, ol.TileRange>} usedTiles Used tiles.
|
||||
*/
|
||||
ol.source.TileSource.prototype.expireCache = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
||||
486
src/ol/structs/linkedmap.js
Normal file
486
src/ol/structs/linkedmap.js
Normal file
@@ -0,0 +1,486 @@
|
||||
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// FIXME replace this with goog.structs.LinkedMap when goog.structs.LinkedMap
|
||||
// adds peekLastKey()
|
||||
|
||||
/**
|
||||
* @fileoverview A LinkedMap data structure that is accessed using key/value
|
||||
* pairs like an ordinary Map, but which guarantees a consistent iteration
|
||||
* order over its entries. The iteration order is either insertion order (the
|
||||
* default) or ordered from most recent to least recent use. By setting a fixed
|
||||
* size, the LRU version of the LinkedMap makes an effective object cache. This
|
||||
* data structure is similar to Java's LinkedHashMap.
|
||||
*
|
||||
* @author brenneman@google.com (Shawn Brenneman)
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('ol.structs.LinkedMap');
|
||||
|
||||
goog.require('goog.structs.Map');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for a LinkedMap datastructure, which combines O(1) map access for
|
||||
* key/value pairs with a linked list for a consistent iteration order. Sample
|
||||
* usage:
|
||||
*
|
||||
* <pre>
|
||||
* var m = new LinkedMap();
|
||||
* m.set('param1', 'A');
|
||||
* m.set('param2', 'B');
|
||||
* m.set('param3', 'C');
|
||||
* alert(m.getKeys()); // param1, param2, param3
|
||||
*
|
||||
* var c = new LinkedMap(5, true);
|
||||
* for (var i = 0; i < 10; i++) {
|
||||
* c.set('entry' + i, false);
|
||||
* }
|
||||
* alert(c.getKeys()); // entry9, entry8, entry7, entry6, entry5
|
||||
*
|
||||
* c.set('entry5', true);
|
||||
* c.set('entry1', false);
|
||||
* alert(c.getKeys()); // entry1, entry5, entry9, entry8, entry7
|
||||
* </pre>
|
||||
*
|
||||
* @param {number=} opt_maxCount The maximum number of objects to store in the
|
||||
* LinkedMap. If unspecified or 0, there is no maximum.
|
||||
* @param {boolean=} opt_cache When set, the LinkedMap stores items in order
|
||||
* from most recently used to least recently used, instead of insertion
|
||||
* order.
|
||||
* @constructor
|
||||
*/
|
||||
ol.structs.LinkedMap = function(opt_maxCount, opt_cache) {
|
||||
/**
|
||||
* The maximum number of entries to allow, or null if there is no limit.
|
||||
* @type {?number}
|
||||
* @private
|
||||
*/
|
||||
this.maxCount_ = opt_maxCount || null;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.cache_ = !!opt_cache;
|
||||
|
||||
this.map_ = new goog.structs.Map();
|
||||
|
||||
this.head_ = new ol.structs.LinkedMap.Node_('', undefined);
|
||||
this.head_.next = this.head_.prev = this.head_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Finds a node and updates it to be the most recently used.
|
||||
* @param {string} key The key of the node.
|
||||
* @return {ol.structs.LinkedMap.Node_} The node or null if not found.
|
||||
* @private
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.findAndMoveToTop_ = function(key) {
|
||||
var node = /** @type {ol.structs.LinkedMap.Node_} */ (this.map_.get(key));
|
||||
if (node) {
|
||||
if (this.cache_) {
|
||||
node.remove();
|
||||
this.insert_(node);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the value for a given key. If this is a caching LinkedMap, the
|
||||
* entry will become the most recently used.
|
||||
* @param {string} key The key to retrieve the value for.
|
||||
* @param {*=} opt_val A default value that will be returned if the key is
|
||||
* not found, defaults to undefined.
|
||||
* @return {*} The retrieved value.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.get = function(key, opt_val) {
|
||||
var node = this.findAndMoveToTop_(key);
|
||||
return node ? node.value : opt_val;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the value for a given key without updating the entry to be the
|
||||
* most recently used.
|
||||
* @param {string} key The key to retrieve the value for.
|
||||
* @param {*=} opt_val A default value that will be returned if the key is
|
||||
* not found.
|
||||
* @return {*} The retrieved value.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.peekValue = function(key, opt_val) {
|
||||
var node = this.map_.get(key);
|
||||
return node ? node.value : opt_val;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a value for a given key. If this is a caching LinkedMap, this entry
|
||||
* will become the most recently used.
|
||||
* @param {string} key The key to retrieve the value for.
|
||||
* @param {*} value A default value that will be returned if the key is
|
||||
* not found.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.set = function(key, value) {
|
||||
var node = this.findAndMoveToTop_(key);
|
||||
if (node) {
|
||||
node.value = value;
|
||||
} else {
|
||||
node = new ol.structs.LinkedMap.Node_(key, value);
|
||||
this.map_.set(key, node);
|
||||
this.insert_(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the first node without making any modifications.
|
||||
* @return {*} The value of the first node or undefined if the map is empty.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.peek = function() {
|
||||
return this.head_.next.value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the last node without making any modifications.
|
||||
* @return {*} The value of the last node or undefined if the map is empty.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.peekLast = function() {
|
||||
return this.head_.prev.value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the key of the last node without making any modifications.
|
||||
* @return {string|undefined} The key of the last node or undefined if the map
|
||||
* is empty.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.peekLastKey = function() {
|
||||
return this.head_.prev.key;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the first node from the list and returns its value.
|
||||
* @return {*} The value of the popped node, or undefined if the map was empty.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.shift = function() {
|
||||
return this.popNode_(this.head_.next);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the last node from the list and returns its value.
|
||||
* @return {*} The value of the popped node, or undefined if the map was empty.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.pop = function() {
|
||||
return this.popNode_(this.head_.prev);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a value from the LinkedMap based on its key.
|
||||
* @param {string} key The key to remove.
|
||||
* @return {boolean} True if the entry was removed, false if the key was not
|
||||
* found.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.remove = function(key) {
|
||||
var node = /** @type {ol.structs.LinkedMap.Node_} */ (this.map_.get(key));
|
||||
if (node) {
|
||||
this.removeNode(node);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a node from the {@code LinkedMap}. It can be overridden to do
|
||||
* further cleanup such as disposing of the node value.
|
||||
* @param {!ol.structs.LinkedMap.Node_} node The node to remove.
|
||||
* @protected
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.removeNode = function(node) {
|
||||
node.remove();
|
||||
this.map_.remove(node.key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The number of items currently in the LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.getCount = function() {
|
||||
return this.map_.getCount();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the cache is empty, false if it contains any items.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.isEmpty = function() {
|
||||
return this.map_.isEmpty();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the maximum number of entries allowed in this object, truncating any
|
||||
* excess objects if necessary.
|
||||
* @param {number} maxCount The new maximum number of entries to allow.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.setMaxCount = function(maxCount) {
|
||||
this.maxCount_ = maxCount || null;
|
||||
if (this.maxCount_ != null) {
|
||||
this.truncate_(this.maxCount_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<string>} The list of the keys in the appropriate order for
|
||||
* this LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.getKeys = function() {
|
||||
return this.map(function(val, key) {
|
||||
return key;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array} The list of the values in the appropriate order for
|
||||
* this LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.getValues = function() {
|
||||
return this.map(function(val, key) {
|
||||
return val;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether a provided value is currently in the LinkedMap. This does not
|
||||
* affect item ordering in cache-style LinkedMaps.
|
||||
* @param {Object} value The value to check for.
|
||||
* @return {boolean} Whether the value is in the LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.contains = function(value) {
|
||||
return this.some(function(el) {
|
||||
return el == value;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether a provided key is currently in the LinkedMap. This does not
|
||||
* affect item ordering in cache-style LinkedMaps.
|
||||
* @param {string} key The key to check for.
|
||||
* @return {boolean} Whether the key is in the LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.containsKey = function(key) {
|
||||
return this.map_.containsKey(key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all entries in this object.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.clear = function() {
|
||||
this.truncate_(0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function on each item in the LinkedMap.
|
||||
*
|
||||
* @see goog.structs.forEach
|
||||
* @param {Function} f The function to call for each item. The function takes
|
||||
* three arguments: the value, the key, and the LinkedMap.
|
||||
* @param {Object=} opt_obj The object context to use as "this" for the
|
||||
* function.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.forEach = function(f, opt_obj) {
|
||||
for (var n = this.head_.next; n != this.head_; n = n.next) {
|
||||
f.call(opt_obj, n.value, n.key, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function on each item in the LinkedMap and returns the results of
|
||||
* those calls in an array.
|
||||
*
|
||||
* @see goog.structs.map
|
||||
* @param {!Function} f The function to call for each item. The function takes
|
||||
* three arguments: the value, the key, and the LinkedMap.
|
||||
* @param {Object=} opt_obj The object context to use as "this" for the
|
||||
* function.
|
||||
* @return {!Array} The results of the function calls for each item in the
|
||||
* LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.map = function(f, opt_obj) {
|
||||
var rv = [];
|
||||
for (var n = this.head_.next; n != this.head_; n = n.next) {
|
||||
rv.push(f.call(opt_obj, n.value, n.key, this));
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function on each item in the LinkedMap and returns true if any of
|
||||
* those function calls returns a true-like value.
|
||||
*
|
||||
* @see goog.structs.some
|
||||
* @param {Function} f The function to call for each item. The function takes
|
||||
* three arguments: the value, the key, and the LinkedMap, and returns a
|
||||
* boolean.
|
||||
* @param {Object=} opt_obj The object context to use as "this" for the
|
||||
* function.
|
||||
* @return {boolean} Whether f evaluates to true for at least one item in the
|
||||
* LinkedMap.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.some = function(f, opt_obj) {
|
||||
for (var n = this.head_.next; n != this.head_; n = n.next) {
|
||||
if (f.call(opt_obj, n.value, n.key, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function on each item in the LinkedMap and returns true only if every
|
||||
* function call returns a true-like value.
|
||||
*
|
||||
* @see goog.structs.some
|
||||
* @param {Function} f The function to call for each item. The function takes
|
||||
* three arguments: the value, the key, and the Cache, and returns a
|
||||
* boolean.
|
||||
* @param {Object=} opt_obj The object context to use as "this" for the
|
||||
* function.
|
||||
* @return {boolean} Whether f evaluates to true for every item in the Cache.
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.every = function(f, opt_obj) {
|
||||
for (var n = this.head_.next; n != this.head_; n = n.next) {
|
||||
if (!f.call(opt_obj, n.value, n.key, this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Appends a node to the list. LinkedMap in cache mode adds new nodes to
|
||||
* the head of the list, otherwise they are appended to the tail. If there is a
|
||||
* maximum size, the list will be truncated if necessary.
|
||||
*
|
||||
* @param {ol.structs.LinkedMap.Node_} node The item to insert.
|
||||
* @private
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.insert_ = function(node) {
|
||||
if (this.cache_) {
|
||||
node.next = this.head_.next;
|
||||
node.prev = this.head_;
|
||||
|
||||
this.head_.next = node;
|
||||
node.next.prev = node;
|
||||
} else {
|
||||
node.prev = this.head_.prev;
|
||||
node.next = this.head_;
|
||||
|
||||
this.head_.prev = node;
|
||||
node.prev.next = node;
|
||||
}
|
||||
|
||||
if (this.maxCount_ != null) {
|
||||
this.truncate_(this.maxCount_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes elements from the LinkedMap if the given count has been exceeded.
|
||||
* In cache mode removes nodes from the tail of the list. Otherwise removes
|
||||
* nodes from the head.
|
||||
* @param {number} count Number of elements to keep.
|
||||
* @private
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.truncate_ = function(count) {
|
||||
for (var i = this.map_.getCount(); i > count; i--) {
|
||||
this.removeNode(this.cache_ ? this.head_.prev : this.head_.next);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the node from the LinkedMap if it is not the head, and returns
|
||||
* the node's value.
|
||||
* @param {!ol.structs.LinkedMap.Node_} node The item to remove.
|
||||
* @return {*} The value of the popped node.
|
||||
* @private
|
||||
*/
|
||||
ol.structs.LinkedMap.prototype.popNode_ = function(node) {
|
||||
if (this.head_ != node) {
|
||||
this.removeNode(node);
|
||||
}
|
||||
return node.value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal class for a doubly-linked list node containing a key/value pair.
|
||||
* @param {string} key The key.
|
||||
* @param {*} value The value.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
ol.structs.LinkedMap.Node_ = function(key, value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The next node in the list.
|
||||
* @type {!ol.structs.LinkedMap.Node_}
|
||||
*/
|
||||
ol.structs.LinkedMap.Node_.prototype.next;
|
||||
|
||||
|
||||
/**
|
||||
* The previous node in the list.
|
||||
* @type {!ol.structs.LinkedMap.Node_}
|
||||
*/
|
||||
ol.structs.LinkedMap.Node_.prototype.prev;
|
||||
|
||||
|
||||
/**
|
||||
* Causes this node to remove itself from the list.
|
||||
*/
|
||||
ol.structs.LinkedMap.Node_.prototype.remove = function() {
|
||||
this.prev.next = this.next;
|
||||
this.next.prev = this.prev;
|
||||
|
||||
delete this.prev;
|
||||
delete this.next;
|
||||
};
|
||||
58
src/ol/tilecache.js
Normal file
58
src/ol/tilecache.js
Normal file
@@ -0,0 +1,58 @@
|
||||
goog.provide('ol.TileCache');
|
||||
|
||||
goog.require('goog.dispose');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileRange');
|
||||
goog.require('ol.structs.LinkedMap');
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} Default high water mark.
|
||||
*/
|
||||
ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK = 512;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.structs.LinkedMap}
|
||||
* @param {number=} opt_highWaterMark High water mark.
|
||||
*/
|
||||
ol.TileCache = function(opt_highWaterMark) {
|
||||
|
||||
goog.base(this, undefined, true);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.highWaterMark_ = goog.isDef(opt_highWaterMark) ?
|
||||
opt_highWaterMark : ol.DEFAULT_TILE_CACHE_HIGH_WATER_MARK;
|
||||
|
||||
};
|
||||
goog.inherits(ol.TileCache, ol.structs.LinkedMap);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can expire cache.
|
||||
*/
|
||||
ol.TileCache.prototype.canExpireCache = function() {
|
||||
return this.getCount() > this.highWaterMark_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object.<string, ol.TileRange>} usedTiles Used tiles.
|
||||
*/
|
||||
ol.TileCache.prototype.expireCache = function(usedTiles) {
|
||||
var tile, zKey;
|
||||
while (this.canExpireCache()) {
|
||||
tile = /** @type {ol.Tile} */ (this.peekLast());
|
||||
zKey = tile.tileCoord.z.toString();
|
||||
if (zKey in usedTiles && usedTiles[zKey].contains(tile.tileCoord)) {
|
||||
break;
|
||||
} else {
|
||||
this.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -48,8 +48,8 @@ ol.tilegrid.XYZ.prototype.forEachTileCoordParentTileRange =
|
||||
if (z < 0) {
|
||||
break;
|
||||
}
|
||||
x = Math.floor(x / 2);
|
||||
y = Math.floor(y / 2);
|
||||
x >>= 1;
|
||||
y >>= 1;
|
||||
tileRange = new ol.TileRange(x, y, x, y);
|
||||
if (callback.call(opt_obj, z, tileRange)) {
|
||||
break;
|
||||
|
||||
@@ -3,14 +3,24 @@ goog.provide('ol.TileQueue');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.structs.PriorityQueue');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.TileState');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(ol.Tile, ol.Coordinate, number): (number|undefined)}
|
||||
* Tile Queue.
|
||||
*
|
||||
* The implementation is inspired from the Closure Library's Heap
|
||||
* class and Python's heapq module.
|
||||
*
|
||||
* http://closure-library.googlecode.com/svn/docs/closure_goog_structs_heap.js.source.html
|
||||
* http://hg.python.org/cpython/file/2.7/Lib/heapq.py
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(ol.Tile, string, ol.Coordinate): number}
|
||||
*/
|
||||
ol.TilePriorityFunction;
|
||||
|
||||
@@ -43,9 +53,9 @@ ol.TileQueue = function(tilePriorityFunction) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.structs.PriorityQueue}
|
||||
* @type {Array.<Array.<*>>}
|
||||
*/
|
||||
this.queue_ = new goog.structs.PriorityQueue();
|
||||
this.heap_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -57,23 +67,49 @@ ol.TileQueue = function(tilePriorityFunction) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Tile} tile Tile.
|
||||
* @param {ol.Coordinate} tileCenter Tile center.
|
||||
* @param {number} tileResolution Tile resolution.
|
||||
* @const {number}
|
||||
*/
|
||||
ol.TileQueue.prototype.enqueue =
|
||||
function(tile, tileCenter, tileResolution) {
|
||||
ol.TileQueue.DROP = Infinity;
|
||||
|
||||
|
||||
/**
|
||||
* Remove and return the highest-priority tile. O(logn).
|
||||
* @private
|
||||
* @return {ol.Tile} Tile.
|
||||
*/
|
||||
ol.TileQueue.prototype.dequeue_ = function() {
|
||||
var heap = this.heap_;
|
||||
goog.asserts.assert(heap.length > 0);
|
||||
var tile = /** @type {ol.Tile} */ (heap[0][1]);
|
||||
if (heap.length == 1) {
|
||||
heap.length = 0;
|
||||
} else {
|
||||
heap[0] = heap.pop();
|
||||
this.siftUp_(0);
|
||||
}
|
||||
var tileKey = tile.getKey();
|
||||
delete this.queuedTileKeys_[tileKey];
|
||||
return tile;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enqueue a tile. O(logn).
|
||||
* @param {ol.Tile} tile Tile.
|
||||
* @param {string} tileSourceKey Tile source key.
|
||||
* @param {ol.Coordinate} tileCenter Tile center.
|
||||
*/
|
||||
ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) {
|
||||
if (tile.getState() != ol.TileState.IDLE) {
|
||||
return;
|
||||
}
|
||||
var tileKey = tile.getKey();
|
||||
if (!(tileKey in this.queuedTileKeys_)) {
|
||||
var priority = this.tilePriorityFunction_(tile, tileCenter, tileResolution);
|
||||
if (goog.isDef(priority)) {
|
||||
this.queue_.enqueue(priority, arguments);
|
||||
var priority = this.tilePriorityFunction_(tile, tileSourceKey, tileCenter);
|
||||
if (priority != ol.TileQueue.DROP) {
|
||||
this.heap_.push([priority, tile, tileSourceKey, tileCenter]);
|
||||
this.queuedTileKeys_[tileKey] = true;
|
||||
} else {
|
||||
// FIXME fire drop event?
|
||||
this.siftDown_(0, this.heap_.length - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -87,15 +123,57 @@ ol.TileQueue.prototype.handleTileChange = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the index of the left child of the node at the given index.
|
||||
* @param {number} index The index of the node to get the left child for.
|
||||
* @return {number} The index of the left child.
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.getLeftChildIndex_ = function(index) {
|
||||
return index * 2 + 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the index of the right child of the node at the given index.
|
||||
* @param {number} index The index of the node to get the right child for.
|
||||
* @return {number} The index of the right child.
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.getRightChildIndex_ = function(index) {
|
||||
return index * 2 + 2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the index of the parent of the node at the given index.
|
||||
* @param {number} index The index of the node to get the parent for.
|
||||
* @return {number} The index of the parent.
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.getParentIndex_ = function(index) {
|
||||
return (index - 1) >> 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make _heap a heap. O(n).
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.heapify_ = function() {
|
||||
for (var i = (this.heap_.length >> 1) - 1; i >= 0; i--) {
|
||||
this.siftUp_(i);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
*/
|
||||
ol.TileQueue.prototype.loadMoreTiles = function() {
|
||||
var tile, tileKey;
|
||||
while (!this.queue_.isEmpty() && this.tilesLoading_ < this.maxTilesLoading_) {
|
||||
tile = (/** @type {Array} */ (this.queue_.dequeue()))[0];
|
||||
tileKey = tile.getKey();
|
||||
delete this.queuedTileKeys_[tileKey];
|
||||
var tile;
|
||||
while (this.heap_.length > 0 && this.tilesLoading_ < this.maxTilesLoading_) {
|
||||
tile = /** @type {ol.Tile} */ (this.dequeue_());
|
||||
goog.events.listen(tile, goog.events.EventType.CHANGE,
|
||||
this.handleTileChange, false, this);
|
||||
tile.load();
|
||||
@@ -104,17 +182,75 @@ ol.TileQueue.prototype.loadMoreTiles = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index The index of the node to move down.
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.siftUp_ = function(index) {
|
||||
var heap = this.heap_;
|
||||
var count = heap.length;
|
||||
var node = heap[index];
|
||||
var startIndex = index;
|
||||
|
||||
while (index < (count >> 1)) {
|
||||
var lIndex = this.getLeftChildIndex_(index);
|
||||
var rIndex = this.getRightChildIndex_(index);
|
||||
|
||||
var smallerChildIndex = rIndex < count &&
|
||||
heap[rIndex][0] < heap[lIndex][0] ?
|
||||
rIndex : lIndex;
|
||||
|
||||
heap[index] = heap[smallerChildIndex];
|
||||
index = smallerChildIndex;
|
||||
}
|
||||
|
||||
heap[index] = node;
|
||||
this.siftDown_(startIndex, index);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} startIndex The index of the root.
|
||||
* @param {number} index The index of the node to move up.
|
||||
* @private
|
||||
*/
|
||||
ol.TileQueue.prototype.siftDown_ = function(startIndex, index) {
|
||||
var heap = this.heap_;
|
||||
var node = heap[index];
|
||||
|
||||
while (index > startIndex) {
|
||||
var parentIndex = this.getParentIndex_(index);
|
||||
if (heap[parentIndex][0] > node[0]) {
|
||||
heap[index] = heap[parentIndex];
|
||||
index = parentIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap[index] = node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
*/
|
||||
ol.TileQueue.prototype.reprioritize = function() {
|
||||
if (!this.queue_.isEmpty()) {
|
||||
var values = /** @type {Array.<Array>} */ (this.queue_.getValues());
|
||||
this.queue_.clear();
|
||||
this.queuedTileKeys_ = {};
|
||||
var i;
|
||||
for (i = 0; i < values.length; ++i) {
|
||||
this.enqueue.apply(this, values[i]);
|
||||
var heap = this.heap_;
|
||||
var i, n = 0, node, priority, tile, tileCenter, tileKey, tileSourceKey;
|
||||
for (i = 0; i < heap.length; ++i) {
|
||||
node = heap[i];
|
||||
tile = /** @type {ol.Tile} */ (node[1]);
|
||||
tileSourceKey = /** @type {string} */ (node[2]);
|
||||
tileCenter = /** @type {ol.Coordinate} */ (node[3]);
|
||||
priority = this.tilePriorityFunction_(tile, tileSourceKey, tileCenter);
|
||||
if (priority == ol.TileQueue.DROP) {
|
||||
tileKey = tile.getKey();
|
||||
delete this.queuedTileKeys_[tileKey];
|
||||
} else {
|
||||
node[0] = priority;
|
||||
heap[n++] = node;
|
||||
}
|
||||
}
|
||||
heap.length = n;
|
||||
this.heapify_();
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
goog.provide('ol.TileUrlFunction');
|
||||
goog.provide('ol.TileUrlFunctionType');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.uri.utils');
|
||||
goog.require('ol.TileCoord');
|
||||
|
||||
@@ -5,6 +5,7 @@ goog.require('goog.array');
|
||||
goog.require('ol.IView');
|
||||
goog.require('ol.IView2D');
|
||||
goog.require('ol.IView3D');
|
||||
goog.require('ol.Object');
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -296,8 +296,10 @@ ol.View2D.prototype.zoom = function(map, delta, opt_anchor, opt_duration) {
|
||||
var currentResolution = this.getResolution();
|
||||
if (goog.isDef(currentResolution) && goog.isDef(opt_duration)) {
|
||||
map.requestRenderFrame();
|
||||
map.addPreRenderFunction(ol.animation.createZoomFrom(
|
||||
currentResolution, opt_duration));
|
||||
map.addPreRenderFunction(ol.animation.createZoomFrom({
|
||||
resolution: currentResolution,
|
||||
duration: opt_duration
|
||||
}));
|
||||
}
|
||||
var resolution = this.constraints_.resolution(currentResolution, delta);
|
||||
this.zoom_(map, resolution, opt_anchor);
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
<script type="text/javascript" src="spec/ol/source/xyz.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/tilecoord.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/tilegrid.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/tilequeue.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/tilerange.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/tileurlfunction.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/control/control.test.js"></script>
|
||||
|
||||
@@ -55,6 +55,21 @@ describe('ol.Extent', function() {
|
||||
expect(destinationExtent.maxX).toRoughlyEqual(5009377.085697311, 1e-9);
|
||||
expect(destinationExtent.maxY).toRoughlyEqual(8399737.889818361, 1e-9);
|
||||
});
|
||||
|
||||
it('takes arbitrary function', function() {
|
||||
var transformFn = function(coordinate) {
|
||||
return new ol.Coordinate(-coordinate.x, -coordinate.y);
|
||||
};
|
||||
var sourceExtent = new ol.Extent(-15, -30, 45, 60);
|
||||
var destinationExtent = sourceExtent.transform(transformFn);
|
||||
expect(destinationExtent).not.toBeUndefined();
|
||||
expect(destinationExtent).not.toBeNull();
|
||||
expect(destinationExtent.minX).toBe(-45);
|
||||
expect(destinationExtent.minY).toBe(-60);
|
||||
expect(destinationExtent.maxX).toBe(15);
|
||||
expect(destinationExtent.maxY).toBe(30);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
68
test/spec/ol/tilequeue.test.js
Normal file
68
test/spec/ol/tilequeue.test.js
Normal file
@@ -0,0 +1,68 @@
|
||||
describe('ol.TileQueue', function() {
|
||||
|
||||
// is the tile queue's array a heap?
|
||||
function isHeap(tq) {
|
||||
var heap = tq.heap_;
|
||||
var i;
|
||||
var key;
|
||||
var leftKey;
|
||||
var rightKey;
|
||||
for (i = 0; i < (heap.length >> 1) - 1; i++) {
|
||||
key = heap[i][0];
|
||||
leftKey = heap[tq.getLeftChildIndex_(i)][0];
|
||||
rightKey = heap[tq.getRightChildIndex_(i)][0];
|
||||
if (leftKey < key || rightKey < key) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function addRandomPriorityTiles(tq, num) {
|
||||
var i, tile, priority;
|
||||
for (i = 0; i < num; i++) {
|
||||
tile = new ol.Tile();
|
||||
priority = Math.floor(Math.random() * 100);
|
||||
tq.heap_.push([priority, tile, '', new ol.Coordinate(0, 0)]);
|
||||
tq.queuedTileKeys_[tile.getKey()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
describe('heapify', function() {
|
||||
it('does convert an arbitrary array into a heap', function() {
|
||||
|
||||
var tq = new ol.TileQueue(function() {});
|
||||
addRandomPriorityTiles(tq, 100);
|
||||
|
||||
tq.heapify_();
|
||||
expect(isHeap(tq)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('reprioritize', function() {
|
||||
it('does reprioritize the array', function() {
|
||||
|
||||
var tq = new ol.TileQueue(function() {});
|
||||
addRandomPriorityTiles(tq, 100);
|
||||
|
||||
tq.heapify_();
|
||||
|
||||
// now reprioritize, changing the priority of 50 tiles and removing the
|
||||
// rest
|
||||
|
||||
var i = 0;
|
||||
tq.tilePriorityFunction_ = function() {
|
||||
if ((i++) % 2 === 0) {
|
||||
return ol.TileQueue.DROP;
|
||||
}
|
||||
return Math.floor(Math.random() * 100);
|
||||
};
|
||||
|
||||
tq.reprioritize();
|
||||
expect(tq.heap_.length).toEqual(50);
|
||||
expect(isHeap(tq)).toBeTruthy();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user