diff --git a/.travis.yml b/.travis.yml index 81476fb67a..25fb64a47c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ sudo: required dist: xenial node_js: - - 14 + - 12 addons: # version 55.0 - 57.x have an issue with screenshots. diff --git a/CHANGELOG.md b/CHANGELOG.md index 027e358259..e74be01006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## Unreleased + +### Improvements +- Screenshots now handle mix-blend-mode settings on top level divs (#1074) + +### Bug Fixes +- Fixed an issue with affine transforms and polygons (#1073) + ## Version 0.20.0 ### Features diff --git a/src/map.js b/src/map.js index 027a94f62d..2cde6fe8e7 100644 --- a/src/map.js +++ b/src/map.js @@ -1820,13 +1820,13 @@ var map = function (arg) { if (layer.renderer() && layer.renderer().api() === 'webgl') { layer.renderer()._renderFrame(); } - drawLayerImageToContext(context, opacity, canvasElem, canvasElem[0]); + drawLayerImageToContext(context, opacity, canvasElem, canvasElem[0], layer.node().css('mix-blend-mode')); }); }); if ((layer.node().children().not('canvas').length || !layer.node().children().length) && (!layer.renderer() || layer.renderer().api() !== 'webgl')) { defer = defer.then(function () { return util.htmlToImage(layer.node(), 1).done(function (img) { - drawLayerImageToContext(context, 1, $([]), img); + drawLayerImageToContext(context, 1, $([]), img, layer.node().css('mix-blend-mode')); }); }); } @@ -1846,7 +1846,7 @@ var map = function (arg) { var attrElem = $(this); defer = defer.then(function () { return util.htmlToImage(attrElem, 1).done(function (img) { - drawLayerImageToContext(context, 1, $([]), img); + drawLayerImageToContext(context, 1, $([]), img, attrElem.css('mix-blend-mode')); }); }); }); @@ -1963,10 +1963,14 @@ var map = function (arg) { * @param {number} opacity The opacity in the range [0, 1]. * @param {object} elem A jQuery element that might have a transform. * @param {HTMLImageObject} img The image or canvas to draw to the canvas. + * @param {string} [mixBlendMode] the mix-blend-mode used to add this layer. * @private */ - function drawLayerImageToContext(context, opacity, elem, img) { + function drawLayerImageToContext(context, opacity, elem, img, mixBlendMode) { context.globalAlpha = opacity; + if (mixBlendMode) { + context.globalCompositeOperation = mixBlendMode; + } var transform = elem.css('transform'); // if the canvas is being transformed, apply the same transformation if (transform && transform.substr(0, 7) === 'matrix(') { @@ -1975,6 +1979,7 @@ var map = function (arg) { context.setTransform(1, 0, 0, 1, 0, 0); } context.drawImage(img, 0, 0); + context.globalCompositeOperation = 'source-over'; } /** diff --git a/tests/cases/map.js b/tests/cases/map.js index e4897e0de7..4e5c5960b2 100644 --- a/tests/cases/map.js +++ b/tests/cases/map.js @@ -827,7 +827,6 @@ describe('geo.core.map', function () { }); }); it('partial opacity', function (done) { - // making a layer transparent is as good as not asking for it layer2.opacity(0.5); m.screenshot().then(function (result) { expect(result).not.toEqual(ss.basic); @@ -853,6 +852,23 @@ describe('geo.core.map', function () { // These tests won't work in PhantomJS. See // https://bugs.webkit.org/show_bug.cgi?id=17352, also 29305 and 129172. if (!isPhantomJS()) { + it('mix-blend-mode multiply', function (done) { + layer2.node().css('mix-blend-mode', 'multiply'); + m.screenshot().then(function (result) { + expect(result).not.toEqual(ss.basic); + expect(result).not.toEqual(ss.onelayer); + layer2.node().css('mix-blend-mode', 'initial'); + done(); + }); + }); + it('mix-blend-mode normal', function (done) { + layer2.node().css('mix-blend-mode', 'normal'); + m.screenshot().then(function (result) { + expect(result).toEqual(ss.basic); + layer2.node().css('mix-blend-mode', 'initial'); + done(); + }); + }); it('layer background', function (done) { var layer3 = m.createLayer('ui'); layer3.node().css('background-image', 'url(/data/tilefancy.png)'); diff --git a/tests/gl-cases/webglContour.js b/tests/gl-cases/webglContour.js index 9536805f55..d3e588dc1e 100644 --- a/tests/gl-cases/webglContour.js +++ b/tests/gl-cases/webglContour.js @@ -107,7 +107,7 @@ describe('webglContour', function () { } myMap.draw(); - imageTest.imageTest(imageName, null, 0.0015, done, myMap.onIdle, 0, 2); + imageTest.imageTest(imageName, null, 0.0015, done, myMap.onIdle, 5000, 2); }); } diff --git a/tests/headed-cases/blog-lines.js b/tests/headed-cases/blog-lines.js index 1044e11dbf..20c8d0f83d 100644 --- a/tests/headed-cases/blog-lines.js +++ b/tests/headed-cases/blog-lines.js @@ -46,13 +46,13 @@ describe('blog-lines example', function () { it('basic', function (done) { $('#map').attr('src', '/examples/blog-lines/index.html?mode=select'); - imageTest.imageTest('exampleBlogLines', '#map', 0.0015, done, ready, 500, 2, '.leaflet-pane'); - }, 10000); + imageTest.imageTest('exampleBlogLines', '#map', 0.0015, done, ready, 5000, 2, '.leaflet-pane'); + }, 20000); it('round line cap', function (done) { $('#map')[0].contentWindow.scrollTo(0, 130); base$ = $('iframe#map')[0].contentWindow.jQuery; base$('#feature').val('linecap-round').trigger('change'); - imageTest.imageTest('exampleBlogLinesRoundCap', '#map', 0.0015, done, ready, 500, 2, '.mapboxgl-canvas'); + imageTest.imageTest('exampleBlogLinesRoundCap', '#map', 0.0015, done, ready, 5000, 2, '.mapboxgl-canvas'); }, 20000); it('10,000 lines in geojs', function (done) { // remove previous contents to ensure we detect new contents @@ -62,6 +62,6 @@ describe('blog-lines example', function () { // this permits a large delta to pass on CI. It visually is rendered // correctly, though with seemingly different aliasing choices by the // renderer - imageTest.imageTest('exampleBlogLines10k', '#map', 0.04, done, null, 1000, 2, '.geojs-map.ready'); + imageTest.imageTest('exampleBlogLines10k', '#map', 0.04, done, null, 5000, 2, '.geojs-map.ready'); }, 10000); });