13

I want to create custom control using Mapbox gl Api. I'm trying to extend Control class and add my own functionality. It doesn't seem working. I'm getting TypeError: "x" is not a constructor error in my console. Even though after extending the class, I'm using super() in constructor function. Am I doing it wrong, is there any other way how to create custom control ?

Linus
  • 149
  • 1
  • 1
  • 5

4 Answers4

26

Your custom control for Mapbox should implement the next interface:

  • onAdd(map) — a function that takes map object and should return your control object. It will be called when your control is added to the map.

  • onRemove(map) — a function that takes map object and will be called when control is removed from the map. You can unbind your event listeners in this method.

Here is a CodePen example. Just use your access token.

sergei
  • 1,146
  • 1
  • 10
  • 19
  • Thanks. Any example how to add a button with click event? – SERG Apr 27 '18 at 07:25
  • 8
    Ok. As I find out if you add a class name mapboxgl-ctrl this.container.className = ‘mapboxgl-ctrl’; - then everything works like a charm – SERG Apr 27 '18 at 07:40
7

Code for a control which looks like Mapbox's one is:

  onAdd(map) {
    this._map = map;
    this._container = document.createElement('div');
    this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
    this._container.addEventListener('contextmenu', (e) => e.preventDefault());
    this._container.addEventListener('click', (e) => this.onClick());

    this._container.innerHTML =
      '<div class="tools-box">' +
      '<button>' +
      '<span class="mapboxgl-ctrl-icon my-image-button" aria-hidden="true" title="Description"></span>' +
      '</button>' +
      '</div>';

    return this._container;
  }

And css of my-image-button is


.my-image-button {
  background: url("data:image/png;base64 etc...");
}

With "home" icon it looks like this:

Custom control with image for mapbox

5

Here is a fully fleshed out version of Артём Ощепков's answer to create a home button.

const homePosition = {
  center: [144, -37],
};

function addHomeButton(map) {
  class HomeButton {
    onAdd(map) {
      const div = document.createElement("div");
      div.className = "mapboxgl-ctrl mapboxgl-ctrl-group";
      div.innerHTML = `<button>
        <svg focusable="false" viewBox="0 0 24 24" aria-hidden="true" style="font-size: 20px;"><title>Reset map</title><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></svg>
        </button>`;
      div.addEventListener("contextmenu", (e) => e.preventDefault());
      div.addEventListener("click", () => map.flyTo(homePosition));

      return div;
    }
  }
  const homeButton = new HomeButton();
  map.addControl(homeButton, "bottom-right");
}
Steve Bennett
  • 114,604
  • 39
  • 168
  • 219
  • This was very useful. Thanks! Small note to make sure the button element has the attributes to match the other controls and for accessibility.: ` – Sherri Feb 07 '23 at 16:18
-1

This is my working code, to create mapbox control, with user drag, click event

standard way is from mapbox offical sample.

alternative way is from Steve Bennett,

I have tested both way, they are the same look, same thing.

You can choose either way.

this is my working code

Here is result, see top right corner, opacity slider, enter image description here

hoogw
  • 4,982
  • 1
  • 37
  • 33