Merge pull request #3571 from ahocevar/vector-wrapx
Add wrapX support for vector layers (canvas renderer only)
This commit is contained in:
@@ -14,7 +14,7 @@ var raster = new ol.layer.Tile({
|
||||
source: new ol.source.MapQuest({layer: 'sat'})
|
||||
});
|
||||
|
||||
var source = new ol.source.Vector();
|
||||
var source = new ol.source.Vector({wrapX: false});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
source: source,
|
||||
|
||||
@@ -19,7 +19,8 @@ var raster = new ol.layer.Tile({
|
||||
var vector = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
url: 'data/geojson/countries.geojson',
|
||||
format: new ol.format.GeoJSON()
|
||||
format: new ol.format.GeoJSON(),
|
||||
wrapX: false
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -4946,7 +4946,8 @@ olx.source.TileWMSOptions.prototype.wrapX;
|
||||
* loader: (ol.FeatureLoader|undefined),
|
||||
* logo: (string|olx.LogoOptions|undefined),
|
||||
* strategy: (ol.LoadingStrategy|undefined),
|
||||
* url: (string|undefined)}}
|
||||
* url: (string|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.source.VectorOptions;
|
||||
@@ -5015,6 +5016,16 @@ olx.source.VectorOptions.prototype.strategy;
|
||||
olx.source.VectorOptions.prototype.url;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap the world horizontally. Default is `true`. For vector editing across the
|
||||
* -180° and 180° meridians to work properly, this should be set to `false`. The
|
||||
* resulting geometry coordinates will then exceed the world bounds.
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.source.VectorOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* crossOrigin: (string|null|undefined),
|
||||
|
||||
@@ -121,6 +121,13 @@ ol.proj.Projection = function(options) {
|
||||
*/
|
||||
this.global_ = goog.isDef(options.global) ? options.global : false;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.canWrapX_ = this.global_ && !goog.isNull(this.extent_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function(number, ol.Coordinate):number}
|
||||
@@ -172,6 +179,14 @@ ol.proj.Projection = function(options) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} The projection is suitable for wrapping the x-axis
|
||||
*/
|
||||
ol.proj.Projection.prototype.canWrapX = function() {
|
||||
return this.canWrapX_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the code for this projection, e.g. 'EPSG:4326'.
|
||||
* @return {string} Code.
|
||||
@@ -255,6 +270,7 @@ ol.proj.Projection.prototype.isGlobal = function() {
|
||||
*/
|
||||
ol.proj.Projection.prototype.setGlobal = function(global) {
|
||||
this.global_ = global;
|
||||
this.canWrapX_ = global && !goog.isNull(this.extent_);
|
||||
};
|
||||
|
||||
|
||||
@@ -281,6 +297,7 @@ ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
|
||||
*/
|
||||
ol.proj.Projection.prototype.setExtent = function(extent) {
|
||||
this.extent_ = extent;
|
||||
this.canWrapX_ = this.global_ && !goog.isNull(extent);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
|
||||
var layer = this.getLayer();
|
||||
if (layer.hasListener(type)) {
|
||||
var transform = goog.isDef(opt_transform) ?
|
||||
opt_transform : this.getTransform(frameState);
|
||||
opt_transform : this.getTransform(frameState, 0);
|
||||
var render = new ol.render.canvas.Immediate(
|
||||
context, frameState.pixelRatio, frameState.extent, transform,
|
||||
frameState.viewState.rotation);
|
||||
@@ -192,10 +192,12 @@ ol.renderer.canvas.Layer.prototype.getImageTransform = goog.abstractMethod;
|
||||
|
||||
/**
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} offsetX Offset on the x-axis in view coordinates.
|
||||
* @protected
|
||||
* @return {!goog.vec.Mat4.Number} Transform.
|
||||
*/
|
||||
ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) {
|
||||
ol.renderer.canvas.Layer.prototype.getTransform =
|
||||
function(frameState, offsetX) {
|
||||
var viewState = frameState.viewState;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
return ol.vec.Mat4.makeTransform2D(this.transform_,
|
||||
@@ -204,7 +206,8 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) {
|
||||
pixelRatio / viewState.resolution,
|
||||
-pixelRatio / viewState.resolution,
|
||||
-viewState.rotation,
|
||||
-viewState.center[0], -viewState.center[1]);
|
||||
-viewState.center[0] + offsetX,
|
||||
-viewState.center[1]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ goog.require('ol');
|
||||
goog.require('ol.RendererType');
|
||||
goog.require('ol.css');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Image');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.Tile');
|
||||
@@ -102,29 +103,41 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
|
||||
var extent = frameState.extent;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var rotation = viewState.rotation;
|
||||
|
||||
ol.vec.Mat4.makeTransform2D(this.transform_,
|
||||
this.canvas_.width / 2, this.canvas_.height / 2,
|
||||
pixelRatio / resolution, -pixelRatio / resolution,
|
||||
-rotation,
|
||||
-viewState.center[0], -viewState.center[1]);
|
||||
var offsetX = 0;
|
||||
if (projection.canWrapX()) {
|
||||
var projectionExtent = projection.getExtent();
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var x = frameState.focus[0];
|
||||
if (x < projectionExtent[0] || x > projectionExtent[2]) {
|
||||
var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth);
|
||||
offsetX = worldWidth * worldsAway;
|
||||
extent = [
|
||||
extent[0] + offsetX, extent[1],
|
||||
extent[2] + offsetX, extent[3]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
var transform = this.getTransform(frameState, offsetX);
|
||||
|
||||
var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
|
||||
var replayGroup = new ol.render.canvas.ReplayGroup(tolerance, extent,
|
||||
resolution);
|
||||
var replayGroup = new ol.render.canvas.ReplayGroup(
|
||||
tolerance, extent, resolution);
|
||||
|
||||
var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
|
||||
extent, this.transform_, rotation);
|
||||
extent, transform, rotation);
|
||||
var composeEvent = new ol.render.Event(type, map, vectorContext,
|
||||
replayGroup, frameState, context, null);
|
||||
map.dispatchEvent(composeEvent);
|
||||
|
||||
replayGroup.finish();
|
||||
if (!replayGroup.isEmpty()) {
|
||||
replayGroup.replay(context, pixelRatio, this.transform_,
|
||||
rotation, {});
|
||||
replayGroup.replay(context, pixelRatio, transform, rotation, {});
|
||||
|
||||
}
|
||||
vectorContext.flush();
|
||||
this.replayGroup = replayGroup;
|
||||
@@ -133,14 +146,21 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @return {ol.renderer.canvas.Layer} Canvas layer renderer.
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} offsetX Offset on the x-axis in view coordinates.
|
||||
* @protected
|
||||
* @return {!goog.vec.Mat4.Number} Transform.
|
||||
*/
|
||||
ol.renderer.canvas.Map.prototype.getCanvasLayerRenderer = function(layer) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
goog.asserts.assertInstanceof(layerRenderer, ol.renderer.canvas.Layer,
|
||||
'layerRenderer is an instance of ol.renderer.canvas.Layer');
|
||||
return /** @type {ol.renderer.canvas.Layer} */ (layerRenderer);
|
||||
ol.renderer.canvas.Map.prototype.getTransform = function(frameState, offsetX) {
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var viewState = frameState.viewState;
|
||||
var resolution = viewState.resolution;
|
||||
return ol.vec.Mat4.makeTransform2D(this.transform_,
|
||||
this.canvas_.width / 2, this.canvas_.height / 2,
|
||||
pixelRatio / resolution, -pixelRatio / resolution,
|
||||
-viewState.rotation,
|
||||
-viewState.center[0] - offsetX,
|
||||
-viewState.center[1]);
|
||||
};
|
||||
|
||||
|
||||
@@ -197,7 +217,8 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchComposeEvent_(ol.render.EventType.POSTCOMPOSE, frameState);
|
||||
this.dispatchComposeEvent_(
|
||||
ol.render.EventType.POSTCOMPOSE, frameState);
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
goog.style.setElementShown(this.canvas_, true);
|
||||
|
||||
@@ -11,6 +11,7 @@ goog.require('ol.render.EventType');
|
||||
goog.require('ol.render.canvas.ReplayGroup');
|
||||
goog.require('ol.renderer.canvas.Layer');
|
||||
goog.require('ol.renderer.vector');
|
||||
goog.require('ol.source.Vector');
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +76,18 @@ goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);
|
||||
ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
function(frameState, layerState, context) {
|
||||
|
||||
var transform = this.getTransform(frameState);
|
||||
var extent = frameState.extent;
|
||||
var focus = frameState.focus;
|
||||
var pixelRatio = frameState.pixelRatio;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
var viewState = frameState.viewState;
|
||||
var projection = viewState.projection;
|
||||
var rotation = viewState.rotation;
|
||||
var projectionExtent = projection.getExtent();
|
||||
var vectorSource = this.getLayer().getSource();
|
||||
goog.asserts.assertInstanceof(vectorSource, ol.source.Vector);
|
||||
|
||||
var transform = this.getTransform(frameState, 0);
|
||||
|
||||
this.dispatchPreComposeEvent(context, frameState, transform);
|
||||
|
||||
@@ -96,9 +108,48 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
|
||||
// see http://jsperf.com/context-save-restore-versus-variable
|
||||
var alpha = replayContext.globalAlpha;
|
||||
replayContext.globalAlpha = layerState.opacity;
|
||||
replayGroup.replay(
|
||||
replayContext, frameState.pixelRatio, transform,
|
||||
frameState.viewState.rotation, frameState.skippedFeatureUids);
|
||||
var noSkip = {};
|
||||
var focusX = focus[0];
|
||||
|
||||
if (vectorSource.getWrapX() && projection.canWrapX() &&
|
||||
!ol.extent.containsExtent(projectionExtent, extent)) {
|
||||
var projLeft = projectionExtent[0];
|
||||
var projRight = projectionExtent[2];
|
||||
// A feature from skippedFeatureUids will only be skipped in the world
|
||||
// that has the frameState's focus, because this is where a feature
|
||||
// overlay for highlighting or selection would render the skipped
|
||||
// feature.
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft <= focusX && focusX <= projRight ?
|
||||
skippedFeatureUids : noSkip);
|
||||
var startX = extent[0];
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var world = 0;
|
||||
var offsetX;
|
||||
while (startX < projectionExtent[0]) {
|
||||
--world;
|
||||
offsetX = worldWidth * world;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ?
|
||||
skippedFeatureUids : noSkip);
|
||||
startX += worldWidth;
|
||||
}
|
||||
world = 0;
|
||||
startX = extent[2];
|
||||
while (startX > projectionExtent[2]) {
|
||||
++world;
|
||||
offsetX = worldWidth * world;
|
||||
transform = this.getTransform(frameState, offsetX);
|
||||
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
|
||||
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ?
|
||||
skippedFeatureUids : noSkip);
|
||||
startX -= worldWidth;
|
||||
}
|
||||
} else {
|
||||
replayGroup.replay(
|
||||
replayContext, pixelRatio, transform, rotation, skippedFeatureUids);
|
||||
}
|
||||
|
||||
if (replayContext != context) {
|
||||
this.dispatchRenderEvent(replayContext, frameState, transform);
|
||||
@@ -194,6 +245,14 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
|
||||
|
||||
var extent = ol.extent.buffer(frameStateExtent,
|
||||
vectorLayerRenderBuffer * resolution);
|
||||
var projectionExtent = viewState.projection.getExtent();
|
||||
|
||||
if (vectorSource.getWrapX() && viewState.projection.canWrapX() &&
|
||||
!ol.extent.containsExtent(projectionExtent, frameState.extent)) {
|
||||
// do not clip when the view crosses the -180° or 180° meridians
|
||||
extent[0] = projectionExtent[0];
|
||||
extent[2] = projectionExtent[2];
|
||||
}
|
||||
|
||||
if (!this.dirty_ &&
|
||||
this.renderedResolution_ == resolution &&
|
||||
|
||||
@@ -9,6 +9,7 @@ goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.renderer.Layer');
|
||||
goog.require('ol.style.IconImageCache');
|
||||
@@ -40,6 +41,7 @@ ol.renderer.Map = function(container, map) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
@@ -136,23 +138,39 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
|
||||
var viewState = frameState.viewState;
|
||||
var viewResolution = viewState.resolution;
|
||||
var viewRotation = viewState.rotation;
|
||||
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function forEachFeatureAtCoordinate(feature) {
|
||||
goog.asserts.assert(goog.isDef(feature), 'received a feature');
|
||||
var key = goog.getUid(feature).toString();
|
||||
if (!(key in features)) {
|
||||
features[key] = true;
|
||||
return callback.call(thisArg, feature, null);
|
||||
}
|
||||
}
|
||||
|
||||
var projection = viewState.projection;
|
||||
|
||||
var translatedCoordinate = coordinate;
|
||||
if (projection.canWrapX()) {
|
||||
var projectionExtent = projection.getExtent();
|
||||
var worldWidth = ol.extent.getWidth(projectionExtent);
|
||||
var x = coordinate[0];
|
||||
if (x < projectionExtent[0] || x > projectionExtent[2]) {
|
||||
var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth);
|
||||
translatedCoordinate = [x + worldWidth * worldsAway, coordinate[1]];
|
||||
}
|
||||
}
|
||||
|
||||
if (!goog.isNull(this.replayGroup)) {
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
result = this.replayGroup.forEachFeatureAtCoordinate(coordinate,
|
||||
viewResolution, viewRotation, {},
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
goog.asserts.assert(goog.isDef(feature), 'received a feature');
|
||||
var key = goog.getUid(feature).toString();
|
||||
if (!(key in features)) {
|
||||
features[key] = true;
|
||||
return callback.call(thisArg, feature, null);
|
||||
}
|
||||
});
|
||||
result = this.replayGroup.forEachFeatureAtCoordinate(translatedCoordinate,
|
||||
viewResolution, viewRotation, {}, forEachFeatureAtCoordinate);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -167,7 +185,8 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
|
||||
layerFilter.call(thisArg2, layer)) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
result = layerRenderer.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, callback, thisArg);
|
||||
layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
|
||||
frameState, callback, thisArg);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ ol.source.State = {
|
||||
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
|
||||
* logo: (string|olx.LogoOptions|undefined),
|
||||
* projection: ol.proj.ProjectionLike,
|
||||
* state: (ol.source.State|undefined)}}
|
||||
* state: (ol.source.State|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
*/
|
||||
ol.source.SourceOptions;
|
||||
|
||||
@@ -72,6 +73,12 @@ ol.source.Source = function(options) {
|
||||
this.state_ = goog.isDef(options.state) ?
|
||||
options.state : ol.source.State.READY;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.wrapX_ = options.wrapX;
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.Source, ol.Object);
|
||||
|
||||
@@ -135,6 +142,14 @@ ol.source.Source.prototype.getState = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean|undefined} Wrap X.
|
||||
*/
|
||||
ol.source.Source.prototype.getWrapX = function() {
|
||||
return this.wrapX_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the attributions of the source.
|
||||
* @param {Array.<ol.Attribution>} attributions Attributions.
|
||||
|
||||
@@ -47,7 +47,8 @@ ol.source.Tile = function(options) {
|
||||
extent: options.extent,
|
||||
logo: options.logo,
|
||||
projection: options.projection,
|
||||
state: options.state
|
||||
state: options.state,
|
||||
wrapX: options.wrapX
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -81,12 +82,6 @@ ol.source.Tile = function(options) {
|
||||
*/
|
||||
this.tmpSize = [0, 0];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.wrapX_ = options.wrapX;
|
||||
|
||||
};
|
||||
goog.inherits(ol.source.Tile, ol.source.Source);
|
||||
|
||||
@@ -221,10 +216,10 @@ ol.source.Tile.prototype.getTilePixelSize =
|
||||
|
||||
|
||||
/**
|
||||
* Handles x-axis wrapping. When `this.wrapX_` is undefined or the projection
|
||||
* is not a global projection, `tileCoord` will be returned unaltered. When
|
||||
* `this.wrapX_` is true, the tile coordinate will be wrapped horizontally.
|
||||
* When `this.wrapX_` is `false`, `null` will be returned for tiles that are
|
||||
* Handles x-axis wrapping. When `wrapX` is `undefined` or the projection is not
|
||||
* a global projection, `tileCoord` will be returned unaltered. When `wrapX` is
|
||||
* `true`, the tile coordinate will be wrapped horizontally.
|
||||
* When `wrapX` is `false`, `null` will be returned for tiles that are
|
||||
* outside the projection extent.
|
||||
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||
* @param {ol.proj.Projection=} opt_projection Projection.
|
||||
@@ -235,8 +230,9 @@ ol.source.Tile.prototype.getWrapXTileCoord =
|
||||
var projection = goog.isDef(opt_projection) ?
|
||||
opt_projection : this.getProjection();
|
||||
var tileGrid = this.getTileGridForProjection(projection);
|
||||
if (goog.isDef(this.wrapX_) && tileGrid.isGlobal(tileCoord[0], projection)) {
|
||||
return this.wrapX_ ?
|
||||
var wrapX = this.getWrapX();
|
||||
if (goog.isDef(wrapX) && tileGrid.isGlobal(tileCoord[0], projection)) {
|
||||
return wrapX ?
|
||||
ol.tilecoord.wrapX(tileCoord, tileGrid, projection) :
|
||||
ol.tilecoord.clipX(tileCoord, tileGrid, projection);
|
||||
} else {
|
||||
|
||||
@@ -79,7 +79,8 @@ ol.source.Vector = function(opt_options) {
|
||||
attributions: options.attributions,
|
||||
logo: options.logo,
|
||||
projection: undefined,
|
||||
state: ol.source.State.READY
|
||||
state: ol.source.State.READY,
|
||||
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -138,6 +138,46 @@ describe('ol.proj', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canWrapX()', function() {
|
||||
|
||||
it('requires an extent for allowing wrapX', function() {
|
||||
var proj = new ol.proj.Projection({
|
||||
code: 'foo',
|
||||
global: true
|
||||
});
|
||||
expect(proj.canWrapX()).to.be(false);
|
||||
proj.setExtent([1, 2, 3, 4]);
|
||||
expect(proj.canWrapX()).to.be(true);
|
||||
proj = new ol.proj.Projection({
|
||||
code: 'foo',
|
||||
global: true,
|
||||
extent: [1, 2, 3, 4]
|
||||
});
|
||||
expect(proj.canWrapX()).to.be(true);
|
||||
proj.setExtent(null);
|
||||
expect(proj.canWrapX()).to.be(false);
|
||||
});
|
||||
|
||||
it('requires global to be true for allowing wrapX', function() {
|
||||
var proj = new ol.proj.Projection({
|
||||
code: 'foo',
|
||||
extent: [1, 2, 3, 4]
|
||||
});
|
||||
expect(proj.canWrapX()).to.be(false);
|
||||
proj.setGlobal(true);
|
||||
expect(proj.canWrapX()).to.be(true);
|
||||
proj = new ol.proj.Projection({
|
||||
code: 'foo',
|
||||
global: true,
|
||||
extent: [1, 2, 3, 4]
|
||||
});
|
||||
expect(proj.canWrapX()).to.be(true);
|
||||
proj.setGlobal(false);
|
||||
expect(proj.canWrapX()).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('transformExtent()', function() {
|
||||
|
||||
it('transforms an extent given projection identifiers', function() {
|
||||
|
||||
90
test/spec/ol/renderer/canvas/canvasmaprenderer.test.js
Normal file
90
test/spec/ol/renderer/canvas/canvasmaprenderer.test.js
Normal file
@@ -0,0 +1,90 @@
|
||||
goog.provide('ol.test.renderer.canvas.Map');
|
||||
|
||||
describe('ol.renderer.canvas.Map', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
|
||||
it('creates a new instance', function() {
|
||||
var map = new ol.Map({
|
||||
target: document.createElement('div')
|
||||
});
|
||||
var renderer = new ol.renderer.canvas.Map(map.viewport_, map);
|
||||
expect(renderer).to.be.a(ol.renderer.canvas.Map);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#renderFrame()', function() {
|
||||
var layer, map, renderer;
|
||||
|
||||
beforeEach(function() {
|
||||
map = new ol.Map({});
|
||||
map.on('postcompose', function() {});
|
||||
layer = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({wrapX: true})
|
||||
});
|
||||
renderer = map.getRenderer();
|
||||
renderer.layerRenderers_ = {};
|
||||
var layerRenderer = new ol.renderer.canvas.Layer(layer);
|
||||
layerRenderer.prepareFrame = function() { return true; };
|
||||
layerRenderer.getImage = function() { return null; };
|
||||
renderer.layerRenderers_[goog.getUid(layer)] = layerRenderer;
|
||||
});
|
||||
|
||||
it('uses correct extent and offset on wrapped worlds', function() {
|
||||
var spy = sinon.spy(renderer, 'getTransform');
|
||||
var proj = new ol.proj.Projection({
|
||||
code: 'foo',
|
||||
extent: [-180, -90, 180, 90],
|
||||
global: true
|
||||
});
|
||||
var frameState = {
|
||||
coordinateToPixelMatrix: map.coordinateToPixelMatrix_,
|
||||
pixelToCoordinateMatrix: map.pixelToCoordinateMatrix_,
|
||||
pixelRatio: 1,
|
||||
size: [100, 100],
|
||||
skippedFeatureUids: {},
|
||||
extent: proj.getExtent(),
|
||||
viewState: {
|
||||
center: [0, 0],
|
||||
projection: proj,
|
||||
resolution: 1,
|
||||
rotation: 0
|
||||
},
|
||||
layerStates: {},
|
||||
layerStatesArray: [{
|
||||
layer: layer,
|
||||
sourceState: 'ready',
|
||||
visible: true,
|
||||
minResolution: 1,
|
||||
maxResolution: 2
|
||||
}],
|
||||
postRenderFunctions: []
|
||||
};
|
||||
frameState.focus = [0, 0];
|
||||
// focus is on real world
|
||||
renderer.renderFrame(frameState);
|
||||
expect(spy.getCall(0).args[1]).to.be(0);
|
||||
expect(renderer.replayGroup.maxExtent_).to.eql([-180, -90, 180, 90]);
|
||||
frameState.focus = [-200, 0];
|
||||
// focus is one world left of the real world
|
||||
renderer.renderFrame(frameState);
|
||||
expect(spy.getCall(1).args[1]).to.be(360);
|
||||
expect(renderer.replayGroup.maxExtent_).to.eql([180, -90, 540, 90]);
|
||||
frameState.focus = [200, 0];
|
||||
// focus is one world right of the real world
|
||||
renderer.renderFrame(frameState);
|
||||
expect(spy.getCall(2).args[1]).to.be(-360);
|
||||
expect(renderer.replayGroup.maxExtent_).to.eql([-540, -90, -180, 90]);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.proj.Projection');
|
||||
goog.require('ol.renderer.canvas.Layer');
|
||||
goog.require('ol.renderer.canvas.Map');
|
||||
goog.require('ol.source.Vector');
|
||||
@@ -5,14 +5,10 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
||||
describe('constructor', function() {
|
||||
|
||||
it('creates a new instance', function() {
|
||||
var map = new ol.Map({
|
||||
target: document.createElement('div')
|
||||
});
|
||||
var layer = new ol.layer.Vector({
|
||||
source: new ol.source.Vector()
|
||||
});
|
||||
var renderer = new ol.renderer.canvas.VectorLayer(map.getRenderer(),
|
||||
layer);
|
||||
var renderer = new ol.renderer.canvas.VectorLayer(layer);
|
||||
expect(renderer).to.be.a(ol.renderer.canvas.VectorLayer);
|
||||
});
|
||||
|
||||
@@ -59,27 +55,24 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
||||
});
|
||||
|
||||
describe('#forEachFeatureAtCoordinate', function() {
|
||||
var renderer;
|
||||
var layer, renderer;
|
||||
|
||||
beforeEach(function() {
|
||||
var map = new ol.Map({});
|
||||
var layer = new ol.layer.Vector({
|
||||
layer = new ol.layer.Vector({
|
||||
source: new ol.source.Vector()
|
||||
});
|
||||
renderer = new ol.renderer.canvas.VectorLayer(
|
||||
map.getRenderer(), layer);
|
||||
renderer = new ol.renderer.canvas.VectorLayer(layer);
|
||||
var replayGroup = {};
|
||||
renderer.replayGroup_ = replayGroup;
|
||||
replayGroup.forEachFeatureAtCoordinate = function(coordinate,
|
||||
resolution, rotation, skippedFeaturesUids, callback) {
|
||||
var geometry = new ol.geom.Point([0, 0]);
|
||||
var feature = new ol.Feature();
|
||||
callback(geometry, feature);
|
||||
callback(geometry, feature);
|
||||
callback(feature);
|
||||
callback(feature);
|
||||
};
|
||||
});
|
||||
|
||||
it('calls callback once per feature', function() {
|
||||
it('calls callback once per feature with a layer as 2nd arg', function() {
|
||||
var spy = sinon.spy();
|
||||
var coordinate = [0, 0];
|
||||
var frameState = {
|
||||
@@ -92,6 +85,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
||||
renderer.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, spy, undefined);
|
||||
expect(spy.callCount).to.be(1);
|
||||
expect(spy.getCall(0).args[1]).to.equal(layer);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user