skip to Main Content

I am displaying many clickable layers that are shown when clicked, but I want to visually distinguish the one that is on from all other by adding a class active to that element when it is clicked ad remove that class when some other element is clicked.

My code is

mapboxgl.accessToken = '<my access token>';
var map = new mapboxgl.Map({
  container: 'map',
  style: '< my style>', // replace this with your style URL
  center: [174.7645, -36.8509],
  zoom: 10,
  pitch: 0,
  bearing: 0,
  antialias: true
});
map.on('style.load', () => {
  map.setFog({});
});

map.on('load', function() {
  map.addSource('data', {
    type: 'geojson',
    data: 'sa2fixedmap.json'
  })

// Add a few layers
map.addLayer({
    'id': 'KULI',
    'type': 'fill',
    'source': 'data',
    'layout': {
      'visibility': 'none'
    },
    'paint': {
      'fill-color': {
        property: 'kuli_geomAgg',
        stops: [
          [0, '#1588ff'],
          [.2, '#69ccfa'],
          [.5, '#ffffb9'],
          [.9, '#ff5959'],
          [1, '#ff0101']
        ]
      }
    }
  }, firstSymbolId);
  map.addLayer({
    'id': 'Train Station',
    'type': 'fill',
    'source': 'data',
    'layout': {
      'visibility': 'none'
    },
    'paint': {
      'fill-color': {
        property: 'station1',
        stops: [
          [0, '#ffffff'],
          [4, '#ffacac'],
          [6, '#ff2b2b'],
          [8, '#ea0000'],
          [10, '#7f0000']
        ]
      }
    }
  }, firstSymbolId);

var alllayersdict = {
'KULI':'KULI',
'Train Station':'transport'
};

// create a dictionary to store the links for each category
var menuLinks = {};

// create a link for each layer and group them by category
for (var key in alllayersdict) {
  var theme = alllayersdict[key];
  var link = document.createElement('a');
  link.href = '#';
  link.id = theme;
  link.textContent = String(key);

  link.onclick = function(e) {
    var clickedLayer = this.textContent;
    e.preventDefault();
    e.stopPropagation();
    for (var key2 in alllayersdict) {
      if (clickedLayer === key2) {
        //class 'active' should be added to the clicked "a" element
        map.setLayoutProperty(key2, 'visibility', 'visible');
      } else {
        //class 'active' should be removed from the "a" element
        map.setLayoutProperty(key2, 'visibility', 'none');
      }
    }
  };
  var layers = document.getElementById('menu');
  layers.appendChild(link);  
  
  // create a new HTML menu element for each category
  if (!menuLinks.hasOwnProperty(theme)) {
    var menu = document.createElement('div');
    menu.className = 'menu-category';
    var title = document.createElement('h3');
    title.textContent = theme;
    menu.appendChild(title);
    var layers = document.createElement('div');
    layers.className = 'menu-layers';
    menu.appendChild(layers);
    menuLinks[theme] = layers;
    document.getElementById('menu').appendChild(menu);
  }

  // add the link to the corresponding HTML menu element
  menuLinks[theme].appendChild(link);
}

How can I achieve this?

2

Answers


  1. Use "element.classList.add" and "element.classList.remove"

    for (var key2 in alllayersdict) {
      if (clickedLayer === key2) {
        key2.classList.add('active') // adds 'active' to classList of key2
        map.setLayoutProperty(key2, 'visibility', 'visible');
      } else {
        key2.classList.remove('active') // removes 'active' fro classList of key2
        map.setLayoutProperty(key2, 'visibility', 'none');
      }
    }
    
    Login or Signup to reply.
  2. The way your code is set up, you can access an anchor <a> element in the for loop in the link.onclick event handler with the following selector string in the querySelector method:

    const anchElem = document.querySelector(`#menu a[id="${alllayersdict[key2]}"]`);
    

    This allows for the .active class to be added or removed within the if else code block:

    if (anchElem) { anchElem.classList.add("active"); } // Add 'active' class
    if (anchElem) { anchElem.classList.remove("active"); } // Remove 'active' class
    

    The above three lines of code are added to the for loop as follows:

    for (var key2 in alllayersdict) {
        const anchElem = document.querySelector(`#menu a[id="${alllayersdict[key2]}"]`);
        if (clickedLayer === key2) {
            //class 'active' should be added to the clicked "a" element
            if (anchElem) { anchElem.classList.add("active"); }
            map.setLayoutProperty(key2, 'visibility', 'visible');
        } else {
            //class 'active' should be removed from the "a" element
            if (anchElem) { anchElem.classList.remove("active"); }
            map.setLayoutProperty(key2, 'visibility', 'none');
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search