Merge pull request #6981 from gberaudo/intermediate_canvas_rendering

Render transparent vector layers to an intermediate canvas
This commit is contained in:
Frédéric Junod
2017-07-12 14:14:13 +02:00
committed by GitHub
3 changed files with 65 additions and 8 deletions

View File

@@ -97,7 +97,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
var drawOffsetX = 0;
var drawOffsetY = 0;
var replayContext;
if (layer.hasListener(ol.render.EventType.RENDER)) {
var transparentLayer = layerState.opacity !== 1;
var hasRenderListeners = layer.hasListener(ol.render.EventType.RENDER);
if (transparentLayer || hasRenderListeners) {
var drawWidth = context.canvas.width;
var drawHeight = context.canvas.height;
if (rotation) {
@@ -113,11 +115,15 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
} else {
replayContext = context;
}
// for performance reasons, context.save / context.restore is not used
// to save and restore the transformation matrix and the opacity.
// see http://jsperf.com/context-save-restore-versus-variable
var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity;
if (!transparentLayer) {
// for performance reasons, context.save / context.restore is not used
// to save and restore the transformation matrix and the opacity.
// see http://jsperf.com/context-save-restore-versus-variable
replayContext.globalAlpha = layerState.opacity;
}
if (replayContext != context) {
replayContext.translate(drawOffsetX, drawOffsetY);
}
@@ -159,11 +165,23 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
width / 2, height / 2);
if (replayContext != context) {
this.dispatchRenderEvent(replayContext, frameState, transform);
context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
if (hasRenderListeners) {
this.dispatchRenderEvent(replayContext, frameState, transform);
}
if (transparentLayer) {
var mainContextAlpha = context.globalAlpha;
context.globalAlpha = layerState.opacity;
context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
context.globalAlpha = mainContextAlpha;
} else {
context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
}
replayContext.translate(-drawOffsetX, -drawOffsetY);
}
replayContext.globalAlpha = alpha;
if (!transparentLayer) {
replayContext.globalAlpha = alpha;
}
}
if (clipped) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -97,6 +97,45 @@ describe('ol.rendering.layer.Vector', function() {
});
});
it('renders transparent layers correctly with the canvas renderer', function(done) {
map = createMap('canvas');
var smallLine = new ol.Feature(new ol.geom.LineString([
[center[0], center[1] - 1],
[center[0], center[1] + 1]
]));
smallLine.setStyle([
new ol.style.Style({
stroke: new ol.style.Stroke({width: 75, color: 'red'})
}),
new ol.style.Style({
stroke: new ol.style.Stroke({width: 45, color: 'white'})
})
]);
source.addFeature(smallLine);
var smallLine2 = new ol.Feature(new ol.geom.LineString([
[center[0], center[1] - 1000],
[center[0], center[1] + 1000]
]));
smallLine2.setStyle([
new ol.style.Style({
stroke: new ol.style.Stroke({width: 35, color: 'blue'})
}),
new ol.style.Style({
stroke: new ol.style.Stroke({width: 15, color: 'green'})
})
]);
source.addFeature(smallLine2);
map.addLayer(new ol.layer.Vector({
source: source,
opacity: 0.5
}));
map.once('postrender', function() {
expectResemble(map, 'spec/ol/layer/expected/vector-canvas-transparent.png',
7, done);
});
});
it('renders rotation correctly with the canvas renderer', function(done) {
map = createMap('canvas');
map.getView().setRotation(Math.PI + Math.PI / 4);