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.
This commit is contained in:
@@ -97,7 +97,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
|||||||
var drawOffsetX = 0;
|
var drawOffsetX = 0;
|
||||||
var drawOffsetY = 0;
|
var drawOffsetY = 0;
|
||||||
var replayContext;
|
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 drawWidth = context.canvas.width;
|
||||||
var drawHeight = context.canvas.height;
|
var drawHeight = context.canvas.height;
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
@@ -113,11 +115,15 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
|||||||
} else {
|
} else {
|
||||||
replayContext = context;
|
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;
|
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) {
|
if (replayContext != context) {
|
||||||
replayContext.translate(drawOffsetX, drawOffsetY);
|
replayContext.translate(drawOffsetX, drawOffsetY);
|
||||||
}
|
}
|
||||||
@@ -159,11 +165,23 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
|||||||
width / 2, height / 2);
|
width / 2, height / 2);
|
||||||
|
|
||||||
if (replayContext != context) {
|
if (replayContext != context) {
|
||||||
this.dispatchRenderEvent(replayContext, frameState, transform);
|
if (hasRenderListeners) {
|
||||||
context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
|
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.translate(-drawOffsetX, -drawOffsetY);
|
||||||
}
|
}
|
||||||
replayContext.globalAlpha = alpha;
|
|
||||||
|
if (!transparentLayer) {
|
||||||
|
replayContext.globalAlpha = alpha;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clipped) {
|
if (clipped) {
|
||||||
|
|||||||
Reference in New Issue
Block a user