Using OpenStreetMap with Ext JS Component


Everyone should be aware Sencha has the class Ext.ux.google.Map to integrate Google maps into your Sencha development. This is all great, however since Google maps is no longer a free production to use, I had to research potential cost with AniMap. Cost was prohibitive running around $700/month for the volume I AniMap required.

A cost of $700/month might be okay for established companies already making solid profits from their product. What about a startup company who knows nothing about income outside of a business proposal estimating consumer acceptance.

OpenStreetMap is a viable open source solution to replace Google maps. However, there is no out of the box simple solution to integrating this with Ext JS.

Using the Leaflet plugin for OpenStreetMap is a great solution in most standard application implementation. Ext JS provides a view hurdles to overcome for some integration. Problems such as sizing the div container for the map display. Getting regular JavaScript to size based on Ext JS components were problematic whereby in most cases the map always rendered larger than the final viewing area with all components in place.

You also want to have functionality in an Ext JS class so control remains within the Ext JS classes and framework. Timing outside of the framework classes in a challenge to say the least.

AniMap is using the following:

  • OpenStreetMap
  • Leaflet
  • Ext JS 7.7
  • Modern Toolkit

Integration was accomplished with the code below.

items: [{
  xtype: 'component',
  id: 'map',
  reference: 'mapCnt',
  responsiveConfig: {
    'width > 1920': {
      width: Ext.getBody().getViewSize().width - 390
    },
    'width <= 1920 && width > 1368': {
      width: Ext.getBody().getViewSize().width - 340
    },
    'width <= 1358': {
      width: Ext.getBody().getViewSize().width - 340
    }
  },
  height: Ext.getBody().getViewSize().height - 140,
  autoEl: {
    tag: 'div'
  }
}];

A component was selected and a an id of ‘map’. I include a reference for accessing this container behind the scenes as needed in the controller.

I’ve included the responsiveConfig so I can control the container size based on the size of the device the user is viewing with. Note, I did not include sizing for a phone as the data to be presented is too complex to fit on a phone form factor. A some point in the future this decision may be revisited.

You may notice the condition for ‘width <= 1920 && width > 1368’ calculate the same size. Immediately you will feel this can and should be combined. I cannot agree more, however Firefox seems to disagree with both of us in how it is rendering. In a 1920 display setting the right end was cropped when the two sizes were combined to one. It will future be needed for future development when zooming details and setting the map zoom for each of the three resolutions.

Already by simply adding the autoEl giving the tag definition of div allows the map content area to size with the Ext JS class that creates the view at run time. This was a great thing since now in all resolutions timing and sizing are within rendering of the view with Ext JS. Something the current version wasn’t able to accomplish as the div was placed using HTML and not an Ext JS component.

Below is the ViewController:

Ext.define('animap.view.animap.AniMapPnlController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.animap-animappnl',

    fnViewSetup: function () {
        let me = this;

        let divWidth = Ext.getBody().getViewSize().width;
        let zoomLvl = 5;
        if (divWidth < 1920) {
            zoomLvl = 4;
        }

        me.map = L.map('map', {
            center: [38.007, -95.844],
            zoom: zoomLvl,
            doubleClickZoom: false,
            scrollWheelZoom: false
        });

        L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '<b>Contributors</b> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap</a> <a href="https://digital.newberry.org/ahcb/" target="_blank">&copy; Newberry Project.</a>',
            subdomains: ['a','b','c']
        }).addTo( me.map );
    }
});

Since OpenStreetMap is inside the Ext JS class it is easy to set the original zoom for the map based on the available screen resolution. From the screenshots below you will see even changing display of information based on screen resolution. Very useful being in the class rather than implementing OpenStreeMap and Leaflet using standalone JavaScript files whereby timing for certain modifications at view rendering is very difficult to overcome.

This is the beginning post about how to make things easier with Ext JS if we first and foremost work within the bounds of Ext JS.

Ext JS is very powerful and works fantastic when you let it do what it does best. Difficulties arise when Ext JS is used for a hammer when what you needed was a screwdriver. By simply using autoEl inside a component integration of OpenStreetMap using Leaflet was a breeze

1368 Resolution
1920 Resolution
27″ Wide Screen

You can see all three screenshots above. Zoom level is critical in this application for the user experience. The 27″ (my dev monitor) clearly has more screen real estate, but even with all that area the zoom factor for both 1920 and mine have to remain the same. The next zoom level on my monitor would cut off part of the U.S.

It is my hope you find this useful in your development in some way. Whether it is OpenStreetMap or some other third party integration into Ext JS is typically easier than 90% of the solutions you find.