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) { diff --git a/test_rendering/spec/ol/layer/expected/vector-canvas-transparent.png b/test_rendering/spec/ol/layer/expected/vector-canvas-transparent.png new file mode 100644 index 0000000000..4bf3ff79d4 Binary files /dev/null and b/test_rendering/spec/ol/layer/expected/vector-canvas-transparent.png differ diff --git a/test_rendering/spec/ol/layer/vector.test.js b/test_rendering/spec/ol/layer/vector.test.js index 4045e064cc..356c2bd3b8 100644 --- a/test_rendering/spec/ol/layer/vector.test.js +++ b/test_rendering/spec/ol/layer/vector.test.js @@ -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);