Switch between GeoJSON layers by using an HTML button within Mapbox GL JS, instead of relying on traditional links

I am currently developing a web map that requires toggling two GeoJSON layers on and off. In the past, I used Mapbox JS to accomplish this task by adding and removing layers with a custom HTML button click. However, I am facing some challenges in achieving the same functionality with Mapbox GL JS. My goal is simple - to toggle the visibility of two layers using HTML buttons instead of links attached to a CSS menu:

var layers = document.getElementById('menu');
layers.appendChild(link);

I attempted to bind the function to the button element but haven't been successful yet:

document.getElementById("toggle-layer-one").onclick = function() {};

HTML:

<button data-balloon="Campsite" data-balloon-pos="right" id="toggle-layer-one"></button>

CSS

#toggle-layer-one {
background-image: url("../Assets/Campsite.svg");
background-size: 70px 70px;
height: 70px;
width: 70px;
border-top: 1px solid #fff;
}

JS

map.on('style.load', function () {
map.addSource("sample", {
    type: "geojson",
    data: "https://raw.githubusercontent.com/aarontaveras/Sample-GeoJSON-Data/master/sample.geojson"
});

map.addLayer({
    "id": "sample-point-one",
    "type": "symbol",
    "source": "sample",
    "filter": ["==", "$type", "Point"],
    "layout": {
        "icon-image": "circle-15",
        "icon-size": 1,
        "icon-anchor": "center",
    }
});

map.setFilter('sample-point-one', ['==', 'region', 'Africa']);

map.addLayer({
    "id": "sample-point-two",
    "type": "symbol",
    "source": "sample",
    "filter": ["==", "$type", "Point"],
    "layout": {
        "icon-image": "circle-15",
        "icon-size": 1,
        "icon-anchor": "center",
    }
});

map.setFilter('sample-point-two', ['==', 'region', 'Asia']);

});

// Toggle layers
var toggleableLayerIds = ["sample-point-one", "sample-point-two"];

for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i];

var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.textContent = id;

link.onclick = function (e) {
    var clickedLayer = this.textContent;
    e.preventDefault();
    e.stopPropagation();

    var visibility = map.getLayoutProperty(clickedLayer, 'visibility');

    if (visibility === 'visible') {
        map.setLayoutProperty(clickedLayer, 'visibility', 'none');
        this.className = '';
    } else {
        this.className = 'active';
        map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
    }
};

var layers = document.getElementById('menu');
layers.appendChild(link);
}

Thank you!

Answer №1

I managed to solve the problem on my own.

HTML:

<a id="test" href="#">TEST</a>

JS:

var toggleLayerId = ["sample-point-one"];

document.getElementById("test").onclick = function (e){
for (var index in toggleLayerId) {
    var clickedLayer = toggleLayerId[index];
    e.preventDefault();
    e.stopPropagation();

    var visibility = map.getLayoutProperty(clickedLayer, 'visibility');

    if (visibility === 'visible') {
        map.setLayoutProperty(clickedLayer, 'visibility', 'none');
        this.className = '';
    } else {
        this.className = 'active';
        map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
    }
}
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

SASS - centering timeline content vertically

I am a beginner in frontend development and I am currently using sass. I have created a custom timeline, but I need assistance in properly aligning the location with the year and timeline marker. Additionally, I would like to position the image description ...

d3: It appears that my routes are replicating themselves, and I am unable to ascertain the cause

I've been diving deep into D3, studying the works of Mike Bostock and other experts in the field. I'm also going through Scott Murray's book on Interactive Data Visualization specifically focusing on D3. At the moment, my project involves c ...

Unable to synchronize Rijdnael encryption across C# and Javascript/Node platforms

I have encountered an issue while trying to convert a Rijndael encryption function from C# to Node. Despite using the same Key, IV, Mode, and Block Size, I am unable to achieve matching results. What could be causing this discrepancy? C# MRE: using System ...

Detecting the preferential usage of -webkit-calc instead of calc through JavaScript feature detection

While it's commonly advised to use feature detection over browser detection in JavaScript, sometimes specific scenarios call for the latter. An example of this can be seen with jQuery 1.9's removal of $.browser. Despite the general recommendatio ...

"Optimizing Performance: Discovering Effective Data Caching

As a developer, I have created two functions - one called Get to fetch data by id from the database and cache it, and another called POST to update data in the database. However, I am facing an issue where I need to cache after both the get and update oper ...

What is the best way to capture GotError [HTTPError]: When the response code 404 (Not Found) occurs in a nodejs

If the URL provided is incorrect and the Got module raises a HTTPError, how can I properly catch the error? Using try-catch does not seem to be effective in this situation. const got = require('got'); got(`https://www.wrongurl.com`) ...

Issue encountered while importing TypeScript files from an external module in a Next.js project

Encountering an issue within my Next.js project with the following project structure: ├── modules/ │ └── auth/ │ ├── index.ts │ ├── page.tsx │ └── package.json └── nextjs-project/ ├─ ...

Error occurs in Query component when using a higher order component (HOC) due to element type

I've developed a custom higher-order component called withInfiniteScroll, designed to enable infinite scrolling functionality for a basic list of data. My aim is to integrate this HOC within Apollo's Query component, but I'm encountering an ...

Customize RequireJS dependencies for flexible dependency injection

Currently, I am faced with integrating a component that would greatly benefit from Dependency Injection (DI) into an existing framework where DI was not considered during its initial design. The configuration defining dependencies is sourced from a backend ...

Why is the responseText from XMLHttpRequest always stripped of tags in AJAX?

Whenever the server sends the XML string to the client using the XMLHttpRequest object, I noticed that when I insert the text inside the div tags, it appears without any tags. However, I actually need the XML tags to be present so that I can parse the cont ...

Utilize jQuery, Flash, or HTML5 to upload an image

Does anyone know of an upload tool or plugin that has a similar look and functionality to the one used on Codecanyon's website? I tried Uploadify, but it doesn't work on all browsers. I need something that is compatible with all browsers, whether ...

Ways to identify when a modal window is being closed in the angular-ui $modal component

I am currently utilizing the $modal from angular-ui to generate a modal window. Below is the code snippet for creating the modal: this.show = function (customModalDefaults, customModalOptions, extraScopeVar) { //Create temporary objects to work with s ...

Getting information from a database using PHP and AngularJS through the $http.get method

Currently, I am utilizing an AngularJS script to retrieve data from an external PHP file that is encoded in JSON within an HTML page. The method $http.get(page2.php) has been employed to fetch a JSON-encoded array located in another file. However, the issu ...

Struggling to make Vue.js transition effects function properly?

I'm having trouble getting a vue.js (version 1) transition to work. I copied the code from their official website, but it's not running the javascript console.logs! Vue.transition('fade', { css: false, enter: function ( ...

Tips for adjusting the position of the second child in my navigation menu using CSS

Struggling with customizing my navigation menu in CSS, I'm seeking assistance. My goal is to have the second child element of the navigation menu on a new line instead of below the first child (refer to the image for clarification). An example of the ...

Intersecting object identification, fresh Function

I'm currently utilizing the "Sinova / Collisions" library on GitHub along with Node.js. The library can be found at https://github.com/Sinova/Collisions. I am in need of a function that allows me to delete all data at once, as the current function for ...

Utilizing the require pattern to integrate JavaScript functionality into HTML

Have: project |- consume_script.js |- index.html Need index.html to be like: <html> <head> </head> <body> <script src="consume_script.js"></script> </body> </html> Issue: consume_script ...

Leveraging static elements in a fluid design using solely CSS whenever feasible

Here's a question that requires some logical thinking rather than technical expertise. I've created a design where the header and footer are always fixed at the top and bottom of the window, respectively. However, the elements inside have percen ...

Unusual glitch spotted on website in real-time, unexpected large circle suddenly materializes on Safari and Internet Explorer

I came across a strange issue on a live site and I need to find a solution quickly. After clicking on the "get a quote" button, a random giant circle with only a border appears on my page when loading a form via ajax. This odd occurrence is visible on Int ...

Does li behave like a separate element from p when it comes to pseudo-class assignments?

While experimenting with multiple pseudo-classes assignments involving p and li content, I made an interesting observation. It seems that adding an extra line of text can sometimes disrupt the pseudo-class assignments. For example, in the code provided be ...