From 645e359cde3c6422f4a0a37043f6c8798f0a915b Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Tue, 4 Jul 2017 15:16:39 +0200 Subject: [PATCH] Render transparent vector layers to an intermediate canvas Until now, the features of transparent vector layers were rendered using the layer opacity. This caused colors to mix together and the opacities to stack up to an higher value than the expected layer opacity. With this commit, the features are rendered at 100% opacity to an intermediate canvas which ensures colors do not mix up even in the case of features using an array of styles. The intermediate canvas is then composed to the map canvas using the layer opacity. Transparent layers are automatically detected, non-transparent layers are not affected by the change. --- src/ol/renderer/canvas/vectorlayer.js | 34 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/ol/renderer/canvas/vectorlayer.js b/src/ol/renderer/canvas/vectorlayer.js index 14f3beeb79..55471f16b8 100644 --- a/src/ol/renderer/canvas/vectorlayer.js +++ b/src/ol/renderer/canvas/vectorlayer.js @@ -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) {