How can I incorporate a new user interface button into Here Maps?

I have set up a default interactive map using Nokia Here Maps v3. The map contains multiple markers grouped together.

Now, I am looking to add a button or some other UI element to the map that, when clicked, will call a function to zoom in as tightly as possible around all the markers in the group. Unfortunately, I haven't been able to find any example code for adding a new UI element, other than an infobubble, or the default UI elements provided with the map, which I don't want to use.

What I had in mind was something similar to the pano button, but positioned at the top left of the map. When this button is clicked, it should trigger my setBounds function to zoom out and encompass all the markers in the group.

Below is the current JavaScript code for my map:

// VUE
var vue1 = new Vue({
  el: '#app',
  data: () => ({
      behavior: null,
      centerCoords: { lng: #centerLon#, lat: #centerLat# },
      defaultLayers: null,
      devices: null,
      markerGroup: null,
      map: null,
      platform: null,
      ui: null,
  }),
  created: function(){
    // Initialize the platform object:
    this.platform = new H.service.Platform({
      'app_id': 'AN ID WOULD GO HERE',
      'app_code': 'A CODE WOULD GO HERE'
    });

    this.defaultLayers = this.platform.createDefaultLayers();
  },
  mounted: function(){
    // Instantiate (and display) a map object:
    this.map = new H.Map(
      document.getElementById('mapContainer'),
      this.defaultLayers.satellite.traffic,
      {
          center: this.centerCoords,
          zoom: 15,
      }
    );

    // Make Map interactive
    // MapEvents enables the event system
    // Behavior implements default interactions for pan/zoom (also on mobile touch environments)
    this.behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(this.map));

    // Create the default UI Components
    this.ui = H.ui.UI.createDefault(this.map, this.defaultLayers, 'en-US');
    this.ui.setUnitSystem(H.ui.UnitSystem.IMPERIAL);

    this.setMarkers();
    setTimeout(this.setBounds, 250);
    setInterval(this.setMarkers, 1 * 60 * 1000);
  },
  computed:{
  },
  methods:{
      setBounds: function(){
          this.map.setViewBounds(this.markerGroup.getBounds());
      },
      setMarkers: function(){
          let self = this;
          // if already present remove markerGroup from map
          if(self.markerGroup){
              self.markerGroup.removeAll();
          }

          //get request
          $.get(
              '/api/v1/getMarkers',
              data => {
                  let zIndex = 1;
                  self.devices = data;

                  // create new marker group from get request.
                  self.markerGroup = new H.map.Group();

                  // add marker group to the map
                  self.map.addObject(self.markerGroup);

                  // add each marker to the marker group
                  self.devices.forEach((el, ind, arr) => {
                      self.addMarkerToGroup(
                          self.markerGroup,
                          {lat: el.latitude, lng: el.longitude},
                          '<div>' + el.serial + '</div>'
                      );
                  });

                  self.map.addEventListener('tap', evt => {
                      if(evt.target instanceof mapsjs.map.Marker){
                          // increase z-index of the marker that was tapped
                          evt.target.setZIndex(zIndex++);
                      }
                  });

                  self.markerGroup.addEventListener('tap', evt => {
                      let bubble = new H.ui.InfoBubble(evt.target.getPosition(), {
                          content: evt.target.getData()
                      });
                      self.ui.addBubble(bubble);
                  }, false);
              },
              'json'
          );
      },
      addMarkerToGroup: function(group, coordinate, html){
          let marker = new H.map.Marker(coordinate);
          marker.setData(html);
          group.addObject(marker);
      }
  }
});

Answer №1

Why not give this a try:

extend = function(subClass, superClass) {   
    function tempConstructor() {}  
    tempConstructor.prototype = superClass.prototype;   
    subClass.superClass_ = superClass.prototype;   
    subClass.prototype = new tempConstructor();   
    subClass.prototype.constructor = subClass;   
    subClass.base = function(me, methodName, var_args) {
        var args = new Array(arguments.length - 2);
        for (var i = 2; i < arguments.length; i++) {
            args[i - 2] = arguments[i];
        }
        return superClass.prototype[methodName].apply(me, args);   
    }; 
};

var ZoomTo = function(opt_options) {   
    'use strict';   
    var options = opt_options || {};

    H.ui.Control.call(this);   
    this.onButtonClick = this.onButtonClick.bind(this);

    // create a button element   
    this.increaseBtn_ = new H.ui.base.Button({
        'label': '<svg class="H_icon H_icon" viewBox="0 0 25 25">' +
            '<path d="M 18.5,11 H 14 V 6.5 c 0,-.8 -.7,-1.5 -1.5,-1.5 -.8,0 -1.5,.7 -1.5,1.5 V 11 H 6' +
            '.5 C 5.7,11 5,11.7 5,12.5 5,13.3 5.7,14 6.5,14 H 11 v 4.5 c 0,.8 .7,1.5 1.5,1.5 .8,0 1.5,' +
            '-.7 1.5,-1.5 V 14 h 4.5 C 19.3,14 20,13.3 20,12.5 20,11.7 19.3,11 18.5,11 z" />' +
            '</svg>',
        'onStateChange': this.onButtonClick   
    });

    //add the buttons as this control's children   
    this.addChild(this.increaseBtn_);

    this.setAlignment(options['alignment'] || 'top-right');

    this.options_ = options; 
}; 

extend(ZoomTo, H.ui.Control);

ZoomTo.prototype.onButtonClick = function(evt) {   
    'use strict';   
    if (evt.currentTarget.getState() === 'down') {
        console.log('Zoom to the set of markers');   
    } 
};

var zoomTo = new ZoomTo(); 
ui.addControl('zoomToMarkers', zoomTo);

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

The Vue3 property 'x' is not recognized on type 'Function' as a global property

I have encountered a strange issue with my Quasar app. I am attempting to define a global variable that consists of metadata about the application in an object format. Despite successfully compiling the app and displaying the correct information on the HTM ...

How can AngularJS utilize variables from an external JavaScript <script> file within an HTML document?

As someone unfamiliar with AngularJS, I have a simple inquiry regarding the subject. The code on my page begins by defining an app and controller: <script> var isisApp = angular.module('isisApp', []); isisApp.controller('Acco ...

"422 (Unprocessable Entity) Error When Submitting a Form in Rails Application

I recently delved into the world of ruby on rails a few days back. My current challenge involves transferring data from html tags to a ruby function using ajax. Below is the error message that has been giving me trouble: POST http://localhost:3000/ajax/o ...

What is the optimal approach for managing server-side data stored as a JavaScript variable?

When dealing with global variables like JSON inserted into a web page server side with PHP, the best way to handle it is up for debate. Options might include leaving it for garbage collection, omitting var initialization and deleting the variable, or simpl ...

Patience is key when awaiting the completion of several promises

I am currently utilizing the SQLStorage feature provided by the Ionic platform. The remove function within this tool returns a promise. Within my code, I have a need to remove multiple values and then execute some additional code once all removals are comp ...

Employing AJAX to send form data to a pair of destinations

Can anyone help me out? I am having trouble using AJAX to submit my form to one location and then to another. Once it's posted to the second location, I want it to send an email with PHP to a specified recipient, but for some reason, it's not wor ...

In order to use DIV jQuery, it is necessary to have at least one input

In my form, there are 5 input fields. On button click using JQuery, I need to validate that at least one of these inputs is filled out. <div id='myForm'> <input name="baz" type="text" /> <input name="bat" type="text" /> ...

Maximum opacity in Three.js fog

My Current Endeavor: I am in the process of developing a lightweight GIS application with topography. One feature I want to implement is atmosphere haze. The Code I'm Working With: (Please bear with me as I have multiple scenes) fogColor = new T ...

Mobile devices do not support HTML5 Video playback

Here is the HTML5 Video code I am using: <div id="lightBox1" class="lightBox"> <video id="video" controls preload="metadata"> <source width="100%" height="470" src="/ImageworkzAsia/video/iworkzvid.mp4" type="video/mp4"> ...

Changing the mouse cursor dynamically with Angular programming

What is the recommended approach for changing the mouse cursor programmatically in Angular? For instance: HTML: <div [style.cursor]="cursorStyle">Content goes here</div> or <div [ngStyle]="{ 'cursor': cursorStyle ...

What could be causing the 403 Error when using Blogger API with AngularJS?

I'm relatively new to working with 3rd Party APIs and I'm currently exploring how to integrate Blogger's API into my AngularJS website to create a blog feed feature. After setting everything up, I've made a request and received a 200 s ...

Error: Unable to find the definition for Image (Next.js)

This new component in my next js project allows me to write a quote on an image and display it on the canvas. However, I am encountering an issue with the Image() function in JavaScript which typically runs on the browser. It seems that Next.js first execu ...

I keep seeing this strange [object HTMLSpanElement] appearing on my HTML page

Thanks for the help, the issue has been resolved and I appreciate your valuable time! ...

Steps to update XmlHttpRequest URL during image upload

I am currently facing an issue with updating images on my website. When I try to update an image, it redirects to the wrong URL instead of the intended one. The form is set to post data to this URL: POST http://127.0.0.1/mgt/upload/processImage/foodImage ...

Developing a RESTful API with Discord.js integrated into Express

Currently, I am faced with the challenge of integrating the Discord.js library into an Express RESTful API. The main issue at hand is how to effectively share the client instance between multiple controllers. The asynchronous initialization process complic ...

What is the best way to rerun a script without having to manually refresh the entire webpage?

If you visit greenb.byethost12.com, you can check out the progress I've made so far. Currently, when you click on the correct answer, it triggers document.location.reload(index.php), causing the entire page to refresh. What I aim for is to have only ...

In Typescript, you can easily group a string into sections that consist of digits like 345-67, along with text containing a

I have a string that looks like this: "[111-11] text here with digits 111, [222-22-22]; 333-33 text here" and I am trying to parse it so that I can extract the code [111-11], [222-22-22], [333-33] along with their respective text descriptions. The challeng ...

Implement a variety of HTTP response codes for a REST endpoint

I'm currently utilizing express to serve the REST API endpoints for a simulated backend. One of the endpoints requires the ability to return different HTTP response codes, while maintaining a 200 status for the other endpoints. Here is a snippet of my ...

Having trouble with Silverlight running JavaScript?

When I try to call a JavaScript function from a SL component using the HtmlPage.Window.Invoke api, it works fine if the function is defined in the page (html). For example: HtmlPage.Window.Invoke("publishValue", topic, jsonObject); However, if I place th ...

Issues with React Router functionality on a live production site are causing complications

I recently created an Amazon-clone UI using create-react-app, but it only displays dummy data. The issue arises after deploying it to Vercel - the routing does not function as expected. When clicking on links, a blank page appears with correct URL paramete ...