Merge branch 'master' of github.com:openlayers/ol3 into vector

This commit is contained in:
Tim Schaub
2013-03-03 09:46:11 +01:00
29 changed files with 715 additions and 295 deletions

View File

@@ -6,8 +6,8 @@
* This loader is used for the hosted examples. It is used in place of the
* development loader (examples/loader.js).
*
* ol.css and ol.js are built with Plovr/Closure, based build/ol.json.
* (`make build` should build them). They are located in the ../build/
* ol.css and ol.js are built with Plovr/Closure, based on build/ol.json.
* (`build.py build` builds them). They are located in the ../build/
* directory, relatively to this script.
*
* The script should be named loader.js. So it needs to be renamed to

View File

@@ -5,9 +5,7 @@
color: #eeeeee;
bottom: 0;
right: 0;
background: #130085; /* @alternate */
background: rgba(0,60,136,0.3);
filter: alpha(opacity=30);
font-family: 'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;
padding: 2px 4px;
}
@@ -60,14 +58,10 @@
height: 22px;
width: 22px;
line-height: 19px;
background: #130085; /* @alternate */
background: rgba(0,60,136,0.5);
filter: alpha(opacity=80);
}
.ol-zoom a:hover {
background: #130085; /* @alternate */
background: rgba(0,60,136,0.7);
filter: alpha(opacity=100);
}
@media only screen and (max-width:600px) {
.ol-zoom a:hover {

View File

@@ -131,7 +131,7 @@ keyboardInteraction.addCallback('l', function() {
view.setCenter(LONDON);
});
keyboardInteraction.addCallback('L', function() {
var start = goog.now();
var start = +new Date();
var duration = 5000;
var bounce = ol.animation.bounce({
resolution: 2 * view.getResolution(),
@@ -166,7 +166,7 @@ keyboardInteraction.addCallback('m', function() {
view.setCenter(MOSCOW);
});
keyboardInteraction.addCallback('M', function() {
var start = goog.now();
var start = +new Date();
var duration = 5000;
var bounce = ol.animation.bounce({
resolution: 2 * view.getResolution(),

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../style.css" type="text/css">
<style type="text/css">
html, body, #map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<link rel="stylesheet" href="../../css/ol.css" type="text/css">
<title>ol3 full-screen demo</title>
<script src="../../build/ol.js" type="text/javascript"></script>
</head>
<body>
<div id="map"></div>
<script src="../full-screen.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -1,82 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../style.css" type="text/css">
<style type="text/css">
html, body, #map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.overlay {
display: none;
font-size: 10pt;
}
.ol-overlaycontainer .overlay {
display: block;
}
#vienna {
text-decoration: none;
color: white;
font-size: 11pt;
font-weight: bold;
text-shadow: black 0.1em 0.1em 0.2em;
}
#popup {
width: 200px;
margin-left: -107px;
margin-bottom: 12px;
border-radius: 5px;
padding: 5px;
}
/* Popup CSS generated with http://cssarrowplease.com/ */
.arrow_box {
position: relative;
background: #88b7d5;
border: 2px solid #c2e1f5;
}
.arrow_box:after, .arrow_box:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.arrow_box:after {
border-color: rgba(136, 183, 213, 0);
border-top-color: #88b7d5;
border-width: 10px;
left: 50%;
margin-left: -10px;
}
.arrow_box:before {
border-color: rgba(194, 225, 245, 0);
border-top-color: #c2e1f5;
border-width: 13px;
left: 50%;
margin-left: -13px;
}
</style>
<link rel="stylesheet" href="../../css/ol.css" type="text/css">
<title>ol3 overlay-and-popup demo</title>
<script src="../../build/ol.js" type="text/javascript"></script>
</head>
<body>
<div id="map">
<!-- Clickable label for Vienna -->
<a class="overlay" id="vienna" target="_blank" href="http://en.wikipedia.org/wiki/Vienna">Vienna</a>
<!-- Popup -->
<div class="overlay arrow_box" id="popup"></div>
</div>
<script src="../overlay-and-popup.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -1,71 +0,0 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="../../css/ol.css" type="text/css">
<link rel="stylesheet" href="../style.css" type="text/css">
<style type="text/css">
.map {
width: 400px;
height: 400px;
border: thin solid #cccccc;
margin: 1em;
}
</style>
<title>ol3 side-by-side demo</title>
<script src="../../build/ol.js" type="text/javascript"></script>
</head>
<body>
<h1>ol3 side-by-side demo</h1>
<table>
<tr>
<th>DOM</th>
<th>WebGL</th>
</tr>
<tr>
<td><div id="domMap" class="map"></div></td>
<td><div id="webglMap" class="map"></div></td>
</tr>
<tr>
<td><div id="domMousePosition" class="mouseposition"></div></td>
<td><div id="webglMousePosition" class="mouseposition"></div></td>
</tr>
</table>
<table>
<tr>
<td>Pan:</td>
<td>drag, arrow keys</td>
</tr>
<tr>
<td>Zoom:</td>
<td>double-click, <code>Shift</code>+double-click, mouse wheel, <code>+</code>/<code>-</code> keys; <code>Shift</code>+drag</td>
</tr>
<tr>
<td>Rotate:</td>
<td><code>Alt</code>+drag, <code>r</code> to reset</td>
</tr>
<tr>
<td>Brightness/contrast:</td>
<td><code>b</code>/<code>B</code>/<code>c</code>/<code>C</code> keys (WebGL only)</td>
</tr>
<tr>
<td>Hue/saturation:</td>
<td><code>h</code>/<code>H</code>/<code>s</code>/<code>S</code> keys (WebGL only)</td>
</tr>
<tr>
<td>Opacity:</td>
<td><code>o</code>/<code>O</code> keys</td>
</tr>
<tr>
<td>Visibility:</td>
<td><code>v</code>/<code>V</code> keys</td>
</tr>
<tr>
<td>Reset</td>
<td><code>0</code> key</td>
</tr>
</table>
<p><b>Notes:</b> The two maps share the same center, resolution, rotation and layers.</p>
<script src="../side-by-side.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -29,9 +29,8 @@ ol.Projection.addProjection(epsg21781);
// We give the single image source a set of resolutions. This prevents the
// source from requesting images of arbitrary resolutions.
var projectionExtent = epsg21781.getExtent();
var maxResolution = Math.max(
projectionExtent.maxX - projectionExtent.minX,
projectionExtent.maxY - projectionExtent.minY) / 256;
var maxResolution = Math.max(projectionExtent.getWidth(),
projectionExtent.getHeight()) / 256;
var resolutions = new Array(10);
for (var i = 0; i < 10; ++i) {
resolutions[i] = maxResolution / Math.pow(2.0, i);

View File

@@ -66,7 +66,7 @@ TileJSON.prototype.tiles;
/**
* @type {!Array.<string>}
* @type {!Array.<string>|undefined}
*/
TileJSON.prototype.grids;

View File

@@ -12,6 +12,8 @@
@exportObjectLiteralProperty ol.MapOptions.renderers Array.<ol.RendererHint>|undefined
@exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined
@exportObjectLiteralProperty ol.MapOptions.target Element|string
@exportObjectLiteralProperty ol.MapOptions.touchPan boolean|undefined
@exportObjectLiteralProperty ol.MapOptions.touchRotateZoom boolean|undefined
@exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined
@exportObjectLiteralProperty ol.MapOptions.zoomControl boolean|undefined
@exportObjectLiteralProperty ol.MapOptions.zoomDelta number|undefined

View File

@@ -2,3 +2,4 @@
@exportProperty ol.animation.bounce
@exportProperty ol.animation.pan
@exportProperty ol.animation.rotate
@exportProperty ol.animation.zoom

5
src/ol/easing.exports Normal file
View File

@@ -0,0 +1,5 @@
@exportSymbol ol.easing
@exportProperty ol.easing.linear
@exportProperty ol.easing.upAndDown
@exportProperty ol.easing.elastic
@exportProperty ol.easing.bounce

View File

@@ -1,2 +1,3 @@
@exportSymbol ol.Extent
@exportProperty ol.Extent.prototype.getHeight
@exportProperty ol.Extent.prototype.getWidth

View File

@@ -1,6 +1,7 @@
goog.provide('ol.ImageUrlFunction');
goog.provide('ol.ImageUrlFunctionType');
goog.require('goog.uri.utils');
goog.require('ol.Extent');
goog.require('ol.Size');

View File

@@ -0,0 +1,119 @@
goog.provide('ol.interaction.Touch');
goog.require('goog.functions');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.Pixel');
goog.require('ol.interaction.Interaction');
/**
* @constructor
* @extends {ol.interaction.Interaction}
*/
ol.interaction.Touch = function() {
goog.base(this);
/**
* @type {boolean}
* @private
*/
this.handled_ = false;
/**
* @type {Object}
* @private
*/
this.trackedTouches_ = {};
/**
* @type {Array.<Object>}
*/
this.targetTouches = [];
};
goog.inherits(ol.interaction.Touch, ol.interaction.Interaction);
/**
* @param {Array.<Object>} touches TouchEvents.
* @return {ol.Pixel} Centroid pixel.
*/
ol.interaction.Touch.centroid = function(touches) {
var length = touches.length;
var clientX = 0;
var clientY = 0;
for (var i = 0; i < length; i++) {
clientX += touches[i].clientX;
clientY += touches[i].clientY;
}
return new ol.Pixel(clientX / length, clientY / length);
};
/**
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
* @private
*/
ol.interaction.Touch.prototype.updateTrackedTouches_ =
function(mapBrowserEvent) {
var event = mapBrowserEvent.browserEvent.getBrowserEvent();
if (goog.isDef(event.targetTouches)) {
// W3C touch events
this.targetTouches = event.targetTouches;
} else {
// IE pointer event
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) {
delete this.trackedTouches_[event.pointerId];
} else {
this.trackedTouches_[event.pointerId] = event;
}
this.targetTouches = goog.object.getValues(this.trackedTouches_);
}
};
/**
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
* @protected
*/
ol.interaction.Touch.prototype.handleTouchMove = goog.nullFunction;
/**
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
* @protected
* @return {boolean} Capture dragging.
*/
ol.interaction.Touch.prototype.handleTouchEnd = goog.functions.FALSE;
/**
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
* @protected
* @return {boolean} Capture dragging.
*/
ol.interaction.Touch.prototype.handleTouchStart = goog.functions.FALSE;
/**
* @inheritDoc
*/
ol.interaction.Touch.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) {
var browserEvent = mapBrowserEvent.browserEvent.getBrowserEvent();
this.updateTrackedTouches_(mapBrowserEvent);
if (this.handled_) {
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHMOVE) {
this.handleTouchMove(mapBrowserEvent);
} else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) {
this.handled_ = this.handleTouchEnd(mapBrowserEvent);
}
}
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHSTART) {
this.handled_ = this.handleTouchStart(mapBrowserEvent);
}
};

View File

@@ -0,0 +1,116 @@
// FIXME works for View2D only
// FIXME opt_kinetic param
goog.provide('ol.interaction.TouchPan');
goog.require('goog.asserts');
goog.require('ol.Coordinate');
goog.require('ol.Kinetic');
goog.require('ol.Pixel');
goog.require('ol.PreRenderFunction');
goog.require('ol.View');
goog.require('ol.ViewHint');
goog.require('ol.interaction.Touch');
/**
* @constructor
* @extends {ol.interaction.Touch}
*/
ol.interaction.TouchPan = function() {
goog.base(this);
/**
* @private
* @type {ol.Kinetic}
*/
this.kinetic_ = new ol.Kinetic(-0.005, 0.05, 100);
/**
* @private
* @type {?ol.PreRenderFunction}
*/
this.kineticPreRenderFn_ = null;
/**
* @type {ol.Pixel}
*/
this.lastCentroid = null;
};
goog.inherits(ol.interaction.TouchPan, ol.interaction.Touch);
/**
* @inheritDoc
*/
ol.interaction.TouchPan.prototype.handleTouchMove = function(mapBrowserEvent) {
goog.asserts.assert(this.targetTouches.length >= 1);
var centroid = ol.interaction.Touch.centroid(this.targetTouches);
if (!goog.isNull(this.lastCentroid)) {
this.kinetic_.update(centroid.x, centroid.y);
var deltaX = this.lastCentroid.x - centroid.x;
var deltaY = centroid.y - this.lastCentroid.y;
var view = mapBrowserEvent.map.getView();
var center = new ol.Coordinate(deltaX, deltaY)
.scale(view.getResolution())
.rotate(view.getRotation())
.add(view.getCenter());
view.setCenter(center);
}
this.lastCentroid = centroid;
};
/**
* @inheritDoc
*/
ol.interaction.TouchPan.prototype.handleTouchEnd =
function(mapBrowserEvent) {
var map = mapBrowserEvent.map;
var view = map.getView();
if (this.targetTouches.length == 0) {
view.setHint(ol.ViewHint.PANNING, -1);
if (this.kinetic_.end()) {
var distance = this.kinetic_.getDistance();
var angle = this.kinetic_.getAngle();
var center = view.getCenter();
this.kineticPreRenderFn_ = this.kinetic_.pan(center);
map.addPreRenderFunction(this.kineticPreRenderFn_);
var centerpx = map.getPixelFromCoordinate(center);
var destpx = new ol.Pixel(
centerpx.x - distance * Math.cos(angle),
centerpx.y - distance * Math.sin(angle));
var dest = map.getCoordinateFromPixel(destpx);
view.setCenter(dest);
}
return false;
} else {
return true;
}
};
/**
* @inheritDoc
*/
ol.interaction.TouchPan.prototype.handleTouchStart =
function(mapBrowserEvent) {
if (this.targetTouches.length >= 1) {
var map = mapBrowserEvent.map;
var view = map.getView();
this.lastCentroid = null;
if (!goog.isNull(this.kineticPreRenderFn_) &&
map.removePreRenderFunction(this.kineticPreRenderFn_)) {
map.requestRenderFrame();
view.setCenter(mapBrowserEvent.frameState.view2DState.center);
this.kineticPreRenderFn_ = null;
}
this.kinetic_.begin();
view.setHint(ol.ViewHint.PANNING, 1);
return true;
} else {
return false;
}
};

View File

@@ -0,0 +1,149 @@
// FIXME works for View2D only
goog.provide('ol.interaction.TouchRotateAndZoom');
goog.require('goog.asserts');
goog.require('ol.View');
goog.require('ol.ViewHint');
goog.require('ol.interaction.Touch');
/**
* @constructor
* @extends {ol.interaction.Touch}
*/
ol.interaction.TouchRotateAndZoom = function() {
goog.base(this);
/**
* @private
* @type {number|undefined}
*/
this.lastAngle_;
/**
* @private
* @type {number|undefined}
*/
this.lastDistance_;
/**
* @private
* @type {boolean}
*/
this.rotating_ = false;
/**
* @private
* @type {number}
*/
this.rotationDelta_ = 0.0;
/**
* @private
* @type {number}
*/
this.rotationThreshold_ = 0.3;
};
goog.inherits(ol.interaction.TouchRotateAndZoom, ol.interaction.Touch);
/**
* @inheritDoc
*/
ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove =
function(mapBrowserEvent) {
goog.asserts.assert(this.targetTouches.length >= 2);
var scaleDelta = 1.0;
var rotationDelta = 0.0;
var centroid = ol.interaction.Touch.centroid(this.targetTouches);
var touch0 = this.targetTouches[0];
var touch1 = this.targetTouches[1];
var dx = touch0.clientX - touch1.clientX;
var dy = touch0.clientY - touch1.clientY;
// angle between touches
var angle = Math.atan2(
touch1.clientY - touch0.clientY,
touch1.clientX - touch0.clientX);
// distance between touches
var distance = Math.sqrt(dx * dx + dy * dy);
if (goog.isDef(this.lastDistance_)) {
scaleDelta = this.lastDistance_ / distance;
}
this.lastDistance_ = distance;
if (goog.isDef(this.lastAngle_)) {
var delta = angle - this.lastAngle_;
this.rotationDelta_ += delta;
if (!this.rotating_ &&
Math.abs(this.rotationDelta_) > this.rotationThreshold_) {
this.rotating_ = true;
}
rotationDelta = delta;
}
this.lastAngle_ = angle;
var map = mapBrowserEvent.map;
var view = map.getView();
// rotate / scale anchor point.
// FIXME: should be the intersection point between the lines:
// touch0,touch1 and previousTouch0,previousTouch1
var viewportPosition = goog.style.getClientPosition(map.getViewport());
centroid.x -= viewportPosition.x;
centroid.y -= viewportPosition.y;
var anchor = map.getCoordinateFromPixel(centroid);
// scale, bypass the resolution constraint
view.zoom_(map, view.getResolution() * scaleDelta, anchor);
// rotate
if (this.rotating_) {
view.rotate(map, view.getRotation() + rotationDelta, anchor);
}
};
/**
* @inheritDoc
*/
ol.interaction.TouchRotateAndZoom.prototype.handleTouchEnd =
function(mapBrowserEvent) {
if (this.targetTouches.length < 2) {
var map = mapBrowserEvent.map;
var view = map.getView();
// take the resolution constraint into account
view.zoomToResolution(map, view.getResolution());
view.setHint(ol.ViewHint.PANNING, -1);
return false;
} else {
return true;
}
};
/**
* @inheritDoc
*/
ol.interaction.TouchRotateAndZoom.prototype.handleTouchStart =
function(mapBrowserEvent) {
if (this.targetTouches.length >= 2) {
var view = mapBrowserEvent.map.getView();
this.lastDistance_ = undefined;
this.lastAngle_ = undefined;
this.rotating_ = false;
this.rotationDelta_ = 0.0;
view.setHint(ol.ViewHint.PANNING, 1);
return true;
} else {
return false;
}
};

View File

@@ -54,6 +54,8 @@ goog.require('ol.interaction.Interaction');
goog.require('ol.interaction.KeyboardPan');
goog.require('ol.interaction.KeyboardZoom');
goog.require('ol.interaction.MouseWheelZoom');
goog.require('ol.interaction.TouchPan');
goog.require('ol.interaction.TouchRotateAndZoom');
goog.require('ol.interaction.condition');
goog.require('ol.layer.Layer');
goog.require('ol.renderer.Map');
@@ -959,6 +961,18 @@ ol.Map.createInteractions_ = function(mapOptions) {
interactions.push(new ol.interaction.DblClickZoom(zoomDelta));
}
var touchPan = goog.isDef(mapOptions.touchPan) ?
mapOptions.touchPan : true;
if (touchPan) {
interactions.push(new ol.interaction.TouchPan());
}
var touchRotateZoom = goog.isDef(mapOptions.touchRotateZoom) ?
mapOptions.touchRotateZoom : true;
if (touchRotateZoom) {
interactions.push(new ol.interaction.TouchRotateAndZoom());
}
var dragPan = goog.isDef(mapOptions.dragPan) ?
mapOptions.dragPan : true;
if (dragPan) {

View File

@@ -3,7 +3,6 @@ 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');
goog.require('goog.events.EventType');
@@ -49,6 +48,20 @@ ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) {
goog.inherits(ol.MapBrowserEvent, ol.MapEvent);
/**
* IE specific events.
* See http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx
* FIXME: replace with goog.events.EventType enum once we use
* goog/events/eventtype.js above r2211
* @enum {string}
*/
ol.MapBrowserEvent.IEEventType = {
MSPOINTERDOWN: 'MSPointerDown',
MSPOINTERMOVE: 'MSPointerMove',
MSPOINTERUP: 'MSPointerUp'
};
/**
* @return {ol.Coordinate} Coordinate.
*/
@@ -114,10 +127,10 @@ ol.MapBrowserEventHandler = function(map) {
/**
* Timestamp for the first click of a double click. Will be set back to 0
* as soon as a double click is detected.
* @type {number}
* @type {?number}
* @private
*/
this.timestamp_ = 0;
this.timestamp_ = null;
/**
* @type {?number}
@@ -137,6 +150,12 @@ ol.MapBrowserEventHandler = function(map) {
*/
this.dragListenerKeys_ = null;
/**
* @type {Array.<number>}
* @private
*/
this.touchListenerKeys_ = null;
/**
* @type {goog.events.BrowserEvent}
* @private
@@ -144,38 +163,32 @@ ol.MapBrowserEventHandler = function(map) {
this.down_ = null;
var element = this.map_.getViewport();
if (!ol.BrowserFeature.HAS_TOUCH) {
this.clickListenerKey_ = goog.events.listen(element,
[goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK],
this.click_, false, this);
}
this.downListenerKey_ = goog.events.listen(element,
ol.BrowserFeature.HAS_TOUCH ?
goog.events.EventType.TOUCHSTART :
goog.events.EventType.MOUSEDOWN,
this.handleDown_, false, this);
this.handleMouseDown_, false, this);
// touch events
this.touchListenerKeys_ = [
goog.events.listen(element, [
goog.events.EventType.TOUCHSTART,
ol.MapBrowserEvent.IEEventType.MSPOINTERDOWN
], this.handleTouchStart_, false, this),
goog.events.listen(element, [
goog.events.EventType.TOUCHMOVE,
ol.MapBrowserEvent.IEEventType.MSPOINTERMOVE
], this.handleTouchMove_, false, this),
goog.events.listen(element, [
goog.events.EventType.TOUCHEND,
ol.MapBrowserEvent.IEEventType.MSPOINTERUP
], this.handleTouchEnd_, false, this)
];
};
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.touchEnableBrowserEvent_ =
function(browserEvent) {
if (ol.BrowserFeature.HAS_TOUCH) {
goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent);
var nativeEvent = browserEvent.getBrowserEvent();
if (nativeEvent.touches && nativeEvent.touches.length) {
var nativeTouch = nativeEvent.touches[0];
browserEvent.clientX = nativeTouch.clientX;
browserEvent.clientY = nativeTouch.clientY;
}
}
};
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
@@ -183,15 +196,15 @@ ol.MapBrowserEventHandler.prototype.touchEnableBrowserEvent_ =
ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) {
if (!this.dragged_) {
var newEvent;
if (browserEvent.type !== goog.events.EventType.DBLCLICK) {
newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent);
this.dispatchEvent(newEvent);
}
if (!this.timestamp_) {
var type = browserEvent.type;
if (this.timestamp_ == 0 || type == goog.events.EventType.DBLCLICK) {
newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent);
this.dispatchEvent(newEvent);
} else if (type == goog.events.EventType.CLICK) {
newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent);
this.dispatchEvent(newEvent);
}
}
};
@@ -201,19 +214,8 @@ ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) {
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handleUp_ = function(browserEvent) {
ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) {
if (this.previous_) {
if (!this.dragged_) {
var now = new Date().getTime();
if (!this.timestamp_ || now - this.timestamp_ > 250) {
this.timestamp_ = now;
} else {
this.timestamp_ = 0;
}
if (ol.BrowserFeature.HAS_TOUCH) {
this.click_(this.down_);
}
}
this.down_ = null;
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
this.dragListenerKeys_ = null;
@@ -231,12 +233,11 @@ ol.MapBrowserEventHandler.prototype.handleUp_ = function(browserEvent) {
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handleDown_ = function(browserEvent) {
ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) {
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent);
this.dispatchEvent(newEvent);
if (!this.previous_) {
this.touchEnableBrowserEvent_(browserEvent);
this.down_ = browserEvent;
this.previous_ = {
clientX: browserEvent.clientX,
@@ -244,22 +245,14 @@ ol.MapBrowserEventHandler.prototype.handleDown_ = function(browserEvent) {
};
this.dragged_ = false;
this.dragListenerKeys_ = [
goog.events.listen(document,
ol.BrowserFeature.HAS_TOUCH ?
goog.events.EventType.TOUCHMOVE :
goog.events.EventType.MOUSEMOVE,
this.drag_, false, this),
goog.events.listen(document,
ol.BrowserFeature.HAS_TOUCH ?
goog.events.EventType.TOUCHEND :
goog.events.EventType.MOUSEUP,
this.handleUp_, false, this)
goog.events.listen(document, goog.events.EventType.MOUSEMOVE,
this.handleMouseMove_, false, this),
goog.events.listen(document, goog.events.EventType.MOUSEUP,
this.handleMouseUp_, false, this)
];
if (browserEvent.type === goog.events.EventType.MOUSEDOWN) {
// prevent browser image dragging on pointer devices
// prevent browser image dragging with the dom renderer
browserEvent.preventDefault();
}
}
};
@@ -267,7 +260,7 @@ ol.MapBrowserEventHandler.prototype.handleDown_ = function(browserEvent) {
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.drag_ = function(browserEvent) {
ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) {
var newEvent;
if (!this.dragged_) {
this.dragged_ = true;
@@ -275,19 +268,64 @@ ol.MapBrowserEventHandler.prototype.drag_ = function(browserEvent) {
ol.MapBrowserEvent.EventType.DRAGSTART, this.map_, this.down_);
this.dispatchEvent(newEvent);
}
this.touchEnableBrowserEvent_(browserEvent);
this.previous_ = {
clientX: browserEvent.clientX,
clientY: browserEvent.clientY
};
// prevent viewport dragging on touch devices
browserEvent.preventDefault();
newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.DRAG, this.map_, browserEvent);
this.dispatchEvent(newEvent);
};
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handleTouchStart_ = function(browserEvent) {
// prevent context menu
browserEvent.preventDefault();
this.down_ = browserEvent;
this.dragged_ = false;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
this.dispatchEvent(newEvent);
};
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handleTouchMove_ = function(browserEvent) {
this.dragged_ = true;
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
this.dispatchEvent(newEvent);
};
/**
* @param {goog.events.BrowserEvent} browserEvent Browser event.
* @private
*/
ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) {
var newEvent = new ol.MapBrowserEvent(
ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
this.dispatchEvent(newEvent);
if (!this.dragged_) {
var now = goog.now();
if (!this.timestamp_ || now - this.timestamp_ > 250) {
this.timestamp_ = now;
} else {
this.timestamp_ = 0;
}
this.click_(this.down_);
}
this.down_ = null;
};
/**
* FIXME empty description for jsdoc
*/
@@ -298,6 +336,10 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
this.dragListenerKeys_ = null;
}
if (!goog.isNull(this.touchListenerKeys_)) {
goog.array.forEach(this.touchListenerKeys_, goog.events.unlistenByKey);
this.touchListenerKeys_ = null;
}
goog.base(this, 'disposeInternal');
};
@@ -309,8 +351,11 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
ol.MapBrowserEvent.EventType = {
CLICK: goog.events.EventType.CLICK,
DBLCLICK: goog.events.EventType.DBLCLICK,
DOWN: 'down',
DRAGSTART: 'dragstart',
DRAG: 'drag',
DRAGEND: 'dragend',
DOWN: 'down'
TOUCHSTART: goog.events.EventType.TOUCHSTART,
TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
TOUCHEND: goog.events.EventType.TOUCHEND
};

View File

@@ -254,7 +254,6 @@ ol.Projection.createProjection = function(projection, defaultCode) {
* @param {ol.TransformFunction} transformFn Transform.
*/
ol.Projection.addTransform = function(source, destination, transformFn) {
var projections = ol.Projection.projections_;
var sourceCode = source.getCode();
var destinationCode = destination.getCode();
var transforms = ol.Projection.transforms_;
@@ -267,6 +266,31 @@ ol.Projection.addTransform = function(source, destination, transformFn) {
};
/**
* Unregisters the conversion function to convert coordinates from the source
* projection to the destination projection. This method is used to clean up
* cached transforms during testing.
*
* @param {ol.Projection} source Source projection.
* @param {ol.Projection} destination Destination projection.
* @return {ol.TransformFunction} transformFn The unregistered transform.
*/
ol.Projection.removeTransform = function(source, destination) {
var sourceCode = source.getCode();
var destinationCode = destination.getCode();
var transforms = ol.Projection.transforms_;
goog.asserts.assert(sourceCode in transforms);
goog.asserts.assert(destinationCode in transforms[sourceCode]);
var transform = transforms[sourceCode][destinationCode];
delete transforms[sourceCode][destinationCode];
var keys = goog.object.getKeys(transforms[sourceCode]);
if (keys.length == 0) {
delete transforms[sourceCode];
}
return transform;
};
/**
* @param {string} code Code which is a combination of authority and identifier
* such as “EPSG:4326”.
@@ -354,7 +378,7 @@ ol.Projection.getTransform = function(source, destination) {
proj4jsDestination = destination;
} else {
proj4jsDestination =
ol.Projection.getProj4jsProjectionFromCode_(source.getCode());
ol.Projection.getProj4jsProjectionFromCode_(destination.getCode());
}
var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
transform =

View File

@@ -129,9 +129,9 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
function isLoaded(tile) {
var isLoaded = function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
}
};
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
@@ -199,6 +199,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
this.scheduleExpireCache(frameState, tileSource);
var transform = this.transform_;

View File

@@ -93,9 +93,9 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
function isLoaded(tile) {
var isLoaded = function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
}
};
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
@@ -217,6 +217,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
this.scheduleExpireCache(frameState, tileSource);
};

View File

@@ -14,7 +14,6 @@ goog.require('ol.TileState');
goog.require('ol.layer.Layer');
goog.require('ol.layer.LayerProperty');
goog.require('ol.layer.LayerState');
goog.require('ol.source.Source');
goog.require('ol.source.TileSource');
@@ -222,24 +221,24 @@ ol.renderer.Layer.prototype.updateAttributions =
/**
* @protected
* @param {Object.<string, Object.<string, ol.TileRange>>} usedTiles Used tiles.
* @param {ol.source.Source} source Source.
* @param {ol.source.TileSource} tileSource Tile source.
* @param {number} z Z.
* @param {ol.TileRange} tileRange Tile range.
*/
ol.renderer.Layer.prototype.updateUsedTiles =
function(usedTiles, source, z, tileRange) {
function(usedTiles, tileSource, z, tileRange) {
// FIXME should we use tilesToDrawByZ instead?
var sourceKey = goog.getUid(source).toString();
var tileSourceKey = goog.getUid(tileSource).toString();
var zKey = z.toString();
if (sourceKey in usedTiles) {
if (zKey in usedTiles[sourceKey]) {
usedTiles[sourceKey][zKey].extend(tileRange);
if (tileSourceKey in usedTiles) {
if (zKey in usedTiles[tileSourceKey]) {
usedTiles[tileSourceKey][zKey].extend(tileRange);
} else {
usedTiles[sourceKey][zKey] = tileRange;
usedTiles[tileSourceKey][zKey] = tileRange;
}
} else {
usedTiles[sourceKey] = {};
usedTiles[sourceKey][zKey] = tileRange;
usedTiles[tileSourceKey] = {};
usedTiles[tileSourceKey][zKey] = tileRange;
}
};
@@ -247,15 +246,15 @@ ol.renderer.Layer.prototype.updateUsedTiles =
/**
* @protected
* @param {Object.<string, Object.<string, boolean>>} wantedTiles Wanted tiles.
* @param {ol.source.Source} source Source.
* @param {ol.source.TileSource} tileSource Tile source.
* @param {ol.TileCoord} tileCoord Tile coordinate.
*/
ol.renderer.Layer.prototype.updateWantedTiles =
function(wantedTiles, source, tileCoord) {
var sourceKey = goog.getUid(source).toString();
function(wantedTiles, tileSource, tileCoord) {
var tileSourceKey = goog.getUid(tileSource).toString();
var coordKey = tileCoord.toString();
if (!(sourceKey in wantedTiles)) {
wantedTiles[sourceKey] = {};
if (!(tileSourceKey in wantedTiles)) {
wantedTiles[tileSourceKey] = {};
}
wantedTiles[sourceKey][coordKey] = true;
wantedTiles[tileSourceKey][coordKey] = true;
};

View File

@@ -365,10 +365,10 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
function isLoaded(tile) {
var isLoaded = function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED &&
mapRenderer.isTileTextureLoaded(tile);
}
};
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
@@ -459,6 +459,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
this.scheduleExpireCache(frameState, tileSource);
goog.vec.Mat4.makeIdentity(this.texCoordMatrix_);

View File

@@ -109,3 +109,14 @@ ol.source.ImageTileSource.prototype.getTile = function(tileCoord) {
ol.source.ImageTileSource.prototype.getTileCoordUrl = function(tileCoord) {
return this.tileUrlFunction(tileCoord);
};
/**
* @inheritDoc
*/
ol.source.ImageTileSource.prototype.useTile = function(tileCoord) {
var key = tileCoord.toString();
if (this.tileCache_.containsKey(key)) {
this.tileCache_.get(key);
}
};

View File

@@ -1,5 +1,6 @@
goog.provide('ol.source.SingleImageWMS');
goog.require('goog.uri.utils');
goog.require('ol.Extent');
goog.require('ol.Image');
goog.require('ol.ImageUrlFunction');

View File

@@ -69,7 +69,7 @@ ol.source.TiledWMS = function(tiledWMSOptions) {
tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction;
}
function tileCoordTransform(tileCoord) {
var tileCoordTransform = function(tileCoord) {
if (tileGrid.getResolutions().length <= tileCoord.z) {
return null;
}
@@ -90,7 +90,7 @@ ol.source.TiledWMS = function(tiledWMSOptions) {
return null;
}
return new ol.TileCoord(tileCoord.z, x, tileCoord.y);
}
};
goog.base(this, {
attributions: tiledWMSOptions.attributions,

View File

@@ -119,3 +119,29 @@ ol.source.TileSource.prototype.getTile = goog.abstractMethod;
ol.source.TileSource.prototype.getTileGrid = function() {
return this.tileGrid;
};
/**
* @param {number} z Z.
* @param {ol.Extent} extent Extent.
*/
ol.source.TileSource.prototype.useLowResolutionTiles = function(z, extent) {
var tileGrid = this.getTileGrid();
var tileRange, x, y, zKey;
// FIXME this should loop up to tileGrid's minZ when implemented
for (; z >= 0; --z) {
tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
this.useTile(z + '/' + x + '/' + y);
}
}
}
};
/**
* Marks a tile coord as being used, without triggering a load.
* @param {string} tileCoordKey Tile coordinate key.
*/
ol.source.TileSource.prototype.useTile = goog.nullFunction;

View File

@@ -77,7 +77,9 @@ describe('ol.Map', function() {
dragPan: false,
keyboard: false,
mouseWheelZoom: false,
shiftDragZoom: false
shiftDragZoom: false,
touchPan: false,
touchRotateZoom: false
};
});

View File

@@ -2,6 +2,27 @@ goog.provide('ol.test.Projection');
describe('ol.Projection', function() {
beforeEach(function() {
spyOn(ol.Projection, 'addTransform').andCallThrough();
});
afterEach(function() {
var argsForCall = ol.Projection.addTransform.argsForCall;
for (var i = 0, ii = argsForCall.length; i < ii; ++i) {
try {
ol.Projection.removeTransform.apply(
ol.Projection, argsForCall[i].splice(0, 2));
} catch (error) {
if (error instanceof goog.asserts.AssertionError) {
// The removeTransform function may have been called explicitly by the
// tests, so we pass.
} else {
throw error;
}
}
}
});
describe('projection equivalence', function() {
function _testAllEquivalent(codes) {
@@ -30,7 +51,6 @@ describe('ol.Projection', function() {
'EPSG:4326'
]);
});
});
describe('identify transform', function() {
@@ -126,8 +146,72 @@ describe('ol.Projection', function() {
});
describe('ol.Projection.getTransform()', function() {
var sm = ol.Projection.getFromCode('GOOGLE');
var gg = ol.Projection.getFromCode('EPSG:4326');
it('returns a transform function', function() {
var transform = ol.Projection.getTransform(sm, gg);
expect(typeof transform).toBe('function');
var coordinate = transform(new ol.Coordinate(-12000000, 5000000));
expect(coordinate.x).toRoughlyEqual(-107.79783409434258, 1e-9);
expect(coordinate.y).toRoughlyEqual(40.91627447067577, 1e-9);
});
});
describe('ol.Projection.getTransformFromCodes()', function() {
it('returns a function', function() {
var transform = ol.Projection.getTransformFromCodes(
'GOOGLE', 'EPSG:4326');
expect(typeof transform).toBe('function');
});
it('returns a transform function', function() {
var transform = ol.Projection.getTransformFromCodes(
'GOOGLE', 'EPSG:4326');
expect(typeof transform).toBe('function');
var coordinate = transform(
new ol.Coordinate(-626172.13571216376, 6887893.4928337997));
expect(coordinate.x).toRoughlyEqual(-5.625, 1e-9);
expect(coordinate.y).toRoughlyEqual(52.4827802220782, 1e-9);
});
});
describe('ol.Projection.removeTransform()', function() {
var extent = new ol.Extent(-180, -90, 180, 90);
var units = ol.ProjectionUnits.DEGREES;
it('removes functions cached by addTransform', function() {
var foo = new ol.Projection('foo', units, extent);
var bar = new ol.Projection('bar', units, extent);
var transform = function() {};
ol.Projection.addTransform(foo, bar, transform);
expect(ol.Projection.transforms_).not.toBeUndefined();
expect(ol.Projection.transforms_.foo).not.toBeUndefined();
expect(ol.Projection.transforms_.foo.bar).toBe(transform);
var removed = ol.Projection.removeTransform(foo, bar);
expect(removed).toBe(transform);
expect(ol.Projection.transforms_.foo).toBeUndefined();
});
});
});
goog.require('goog.array');
goog.require('ol.Coordinate');
goog.require('ol.Extent');
goog.require('ol.Projection');
goog.require('ol.ProjectionUnits');