Merge pull request #8225 from ahocevar/image-vector-fixes

renderMode: 'image' fixes for ol/layer/Vector
This commit is contained in:
Andreas Hocevar
2018-05-25 14:46:53 +02:00
committed by GitHub
4 changed files with 92 additions and 33 deletions

View File

@@ -43,12 +43,14 @@ import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style.
* @property {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} [style] Layer style. See
* {@link module:ol/style} for default style which will be used if this is not defined.
* @property {number} [maxTilesLoading=16] Maximum number tiles to load simultaneously.
* @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will be
* recreated during animations. This means that no vectors will be shown clipped, but the setting
* will have a performance impact for large amounts of vector data. When set to `false`, batches
* will be recreated when no animation is active.
* @property {boolean} [updateWhileInteracting=false] When set to `true`, feature batches will be
* recreated during interactions. See also `updateWhileAnimating`.
* @property {boolean} [updateWhileAnimating=false] When set to `true` and `renderMode`
* is `vector`, feature batches will be recreated during animations. This means that no
* vectors will be shown clipped, but the setting will have a performance impact for large
* amounts of vector data. When set to `false`, batches will be recreated when no animation
* is active.
* @property {boolean} [updateWhileInteracting=false] When set to `true` and `renderMode`
* is `vector`, feature batches will be recreated during interactions. See also
* `updateWhileAnimating`.
*/

View File

@@ -132,8 +132,9 @@ CanvasImageLayerRenderer.prototype.prepareFrame = function(frameState, layerStat
const hints = frameState.viewHints;
const vectorRenderer = this.vectorRenderer_;
let renderedExtent = frameState.extent;
if (layerState.extent !== undefined) {
if (!vectorRenderer && layerState.extent !== undefined) {
renderedExtent = getIntersection(renderedExtent, layerState.extent);
}
@@ -146,7 +147,7 @@ CanvasImageLayerRenderer.prototype.prepareFrame = function(frameState, layerStat
projection = sourceProjection;
}
}
const vectorRenderer = this.vectorRenderer_;
let skippedFeatures = this.skippedFeatures_;
if (vectorRenderer) {
const context = vectorRenderer.context;
const imageFrameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, frameState, {
@@ -158,25 +159,25 @@ CanvasImageLayerRenderer.prototype.prepareFrame = function(frameState, layerStat
rotation: 0
}))
}));
const skippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
(vectorRenderer.replayGroupChanged ||
!equals(skippedFeatures, this.skippedFeatures_))) {
context.canvas.width = imageFrameState.size[0] * pixelRatio;
context.canvas.height = imageFrameState.size[1] * pixelRatio;
vectorRenderer.composeFrame(imageFrameState, layerState, context);
this.image_ = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas);
this.skippedFeatures_ = skippedFeatures;
}
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
(vectorRenderer.replayGroupChanged ||
!equals(skippedFeatures, newSkippedFeatures))) {
context.canvas.width = imageFrameState.size[0] * pixelRatio;
context.canvas.height = imageFrameState.size[1] * pixelRatio;
vectorRenderer.compose(context, imageFrameState, layerState);
skippedFeatures = newSkippedFeatures;
callback();
}
});
} else {
image = imageSource.getImage(
renderedExtent, viewResolution, pixelRatio, projection);
if (image) {
const loaded = this.loadImage(image);
if (loaded) {
this.image_ = image;
}
}
}
if (image && this.loadImage(image)) {
this.image_ = image;
this.skippedFeatures_ = skippedFeatures;
}
}

View File

@@ -116,10 +116,11 @@ CanvasVectorLayerRenderer.prototype.disposeInternal = function() {
/**
* @inheritDoc
* @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/PluggableMap~FrameState} frameState Frame state.
* @param {module:ol/layer/Layer~State} layerState Layer state.
*/
CanvasVectorLayerRenderer.prototype.composeFrame = function(frameState, layerState, context) {
CanvasVectorLayerRenderer.prototype.compose = function(context, frameState, layerState) {
const extent = frameState.extent;
const pixelRatio = frameState.pixelRatio;
const skippedFeatureUids = layerState.managed ?
@@ -132,8 +133,6 @@ CanvasVectorLayerRenderer.prototype.composeFrame = function(frameState, layerSta
let transform = this.getTransform(frameState, 0);
this.preCompose(context, frameState, transform);
// clipped rendering if layer extent is set
const clipExtent = layerState.extent;
const clipped = clipExtent !== undefined;
@@ -207,8 +206,6 @@ CanvasVectorLayerRenderer.prototype.composeFrame = function(frameState, layerSta
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids);
startX -= worldWidth;
}
// restore original transform for render and compose events
transform = this.getTransform(frameState, 0);
}
rotateAtOffset(replayContext, rotation,
width / 2, height / 2);
@@ -236,8 +233,17 @@ CanvasVectorLayerRenderer.prototype.composeFrame = function(frameState, layerSta
if (clipped) {
context.restore();
}
this.postCompose(context, frameState, layerState, transform);
};
/**
* @inheritDoc
*/
CanvasVectorLayerRenderer.prototype.composeFrame = function(frameState, layerState, context) {
const transform = this.getTransform(frameState, 0);
this.preCompose(context, frameState, transform);
this.compose(context, frameState, layerState);
this.postCompose(context, frameState, layerState, transform);
};

View File

@@ -2,6 +2,8 @@ import Map from '../../../../../src/ol/Map.js';
import View from '../../../../../src/ol/View.js';
import ImageLayer from '../../../../../src/ol/layer/Image.js';
import VectorLayer from '../../../../../src/ol/layer/Vector.js';
import Feature from '../../../../../src/ol/Feature.js';
import Point from '../../../../../src/ol/geom/Point.js';
import Projection from '../../../../../src/ol/proj/Projection.js';
import Static from '../../../../../src/ol/source/ImageStatic.js';
import VectorSource from '../../../../../src/ol/source/Vector.js';
@@ -106,10 +108,10 @@ describe('ol.renderer.canvas.ImageLayer', function() {
});
afterEach(function() {
layer.dispose();
vectorRenderer1.dispose();
vectorRenderer2.dispose();
imageRenderer.dispose();
layer.dispose();
});
it('cleans up an existing vectorRenderer', function() {
@@ -119,6 +121,54 @@ describe('ol.renderer.canvas.ImageLayer', function() {
imageRenderer.setVectorRenderer(vectorRenderer2);
expect(spy.called).to.be(true);
});
});
describe('Vector image rendering', function() {
let map, div, layer;
beforeEach(function() {
layer = new VectorLayer({
renderMode: 'image',
source: new VectorSource({
features: [new Feature(new Point([0, 0]))]
})
});
div = document.createElement('div');
div.style.width = div.style.height = '100px';
document.body.appendChild(div);
map = new Map({
target: div,
layers: [layer],
view: new View({
center: [0, 0],
zoom: 2
})
});
});
afterEach(function() {
map.setTarget(null);
document.body.removeChild(div);
map.dispose();
});
it('dispatches precompose and postcompose events on the vector layer', function(done) {
let precompose = 0;
let postcompose = 0;
layer.on('precompose', function() {
++precompose;
});
layer.on('postcompose', function() {
++postcompose;
});
map.once('postrender', function() {
expect(precompose).to.be(1);
expect(postcompose).to.be(1);
done();
});
});
});
});