1

I am trying to color my tileLayer mask differently and I found the colorFilter plugin. I can't seem to figure how to use the color filter tile created in my mask tileLayer.

let map = L.map("map", {
  zoom: 16,
  center: [35.9734, 117.7926]
});

let sampleFilter = [
  'bright:85%',
  'hue:83deg',
  'saturate:97%'
];

// background layer -- color filter plugin
let myTileLayer = L.tileLayer.colorFilter('https://{s}.tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=xxxxxxxxxxxxxxxx', {
  attribution: '',
  filter: sampleFilter,
}).addTo(map);
    
// mask layer -- tileLayer mask plugin
let mask = L.tileLayer.mask('https://{s}.tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=xxxxxxxxxxxxxxxx', {
   maskSize: 512,
   maxZoom: 18,
   maxNativeZoom: 17
 }).addTo(map);
    
mask.setCenter(e.containerPoint);
2
  • If you look at the plugin docs github.com/xtk93x/Leaflet.TileLayer.ColorFilter, you are missing filter option, where you specify your color filter.
    – TomazicM
    Jun 17, 2020 at 19:38
  • The filter option was missed in error; I will correct that. But my main question is how to use the "myTileLayer" in "mask".
    – b_jugger
    Jun 17, 2020 at 19:40

1 Answer 1

3

This is possible, but there is no out-of-the-box solution. You have to create your own plugin, which combines leaflet-tilelayer-mask and Leaflet.TileLayer.ColorFilter plugins.

New plugin, let's name it L.TileLayer.ColorFilterMask, is created by extending L.TileLayer.ColorFilter instead of L.TileLayer when creating new mask plugin.

Code in leaflet-tilelayer-mask.js has to be modified in three places. First initial definition line:

L.TileLayer.ColorFilterMask = L.TileLayer.ColorFilter.extend({

Then we insert color filter at the end of _initContainer method:

_initContainer: function() {
  .
  .
  .
  this._container.style.filter = this.colorFilter();
},

Then at the end layer creation function is modified:

L.tileLayer.colorFilterMask = function(url, options) {
  return new L.TileLayer.ColorFilterMask(url, options);
};

When linking plugin modules, first leaflet-tilelayer-colorfilter.js has to be linked and then newly created leaflet-tilelayer-mask.js.

Colored mask layer is then created simply by:

let sampleFilter = [
  'bright:85%',
  'hue:83deg',
  'saturate:97%'
];

    
let coloredMask = L.tileLayer.colorFilterMask('https://{s}.tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=xxxxxxxxxxxxxxxx', {
  maskSize: 512,
  filter: sampleFilter,
  maxZoom: 18,
  maxNativeZoom: 17
}).addTo(map);

Here is working JSFiddle: https://jsfiddle.net/TomazicM/w0z1t8L6/

EDIT: After some more testing this solution seems to be working only in Firefox. Reason for this is that mask plugin does not create it's masked layer in <div> element but in <svg> element that contains <image> links to layer tiles. Color filter is then applied to this layer through style attribute, for example style="filter: brightness(85%) hue-rotate(83deg) saturate(97%);". This kind of filter works for <svg> with embedded images only in Firefox. I tried also with -webkit-filter, but it didn't help.

This problem can be solved with a little dirty trick of creating separate map pane for masked layer and then instead of applying color filter through combined mask and color filter plugin, just using mask plugin and then applying color filter through map pane style.

So there is no need to use color filter plugin, just mask plugin and setting color filter on map pane element style:

let myPane = map.createPane('my-pane');
myPane.style.filter = 'brightness(85%) hue-rotate(83deg) saturate(97%)';

let mask = L.tileLayer.mask('https://{s}.tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=xxxxxxxxxxxxxxxx', {
  maskSize: 512,
  maxZoom: 18,
  maxNativeZoom: 17,
  pane: 'my-pane'
}).addTo(map);
11
  • Awesome. Let me give it a try and revert.
    – b_jugger
    Jun 18, 2020 at 20:31
  • I have tried all that you hinted on including ensuring that on loading my scripts in *.html file that the colorfilter plugin file comes first before the newly created but doesn't still work. I noticed that it should be necessary to pass the filter option in thee options of the mask, that is in the newly created plugin. options: { maskUrl: defaultMaskUrl, maskSize: 512 },
    – b_jugger
    Jun 20, 2020 at 16:21
  • I added working JSFiddle. Code for both plugins is included in the code.
    – TomazicM
    Jun 20, 2020 at 17:51
  • 1
    This is getting interesting. It works in Firefox but not in Chrome. If I'll have time I'll have a look what could be the reason.
    – TomazicM
    Jun 20, 2020 at 18:38
  • 1
    See my new solution.
    – TomazicM
    Jun 20, 2020 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.