EPolle_TensingInternational

ArcGIS JavaScript with UK data - URL.searchParams

Blog Post created by EPolle_TensingInternational Champion on Jul 6, 2020

ArcGIS JavaScript with UK data - Table of Content 

 

Setting x, y and zoom level in url

to retain map view

 

When you zoom in on a particular location on a map, you sometimes wish you could retain that map view, e.g. to share it with someone else. That's why we were looking for a way to get the x, y and zoom level from the search parameters in our url. But not only do we want to be able to read the values from the query string (i.e. everything behind the question mark), we also want to be able to set them, and to modify them whenever the map view changes, i.e. when the user pans and zooms around on the map.

 

Below is a description of the functionality we use to grab the x an y coordinates (in British National Grid, rounded to the full meter) and to modify the url.


URLSearchParams and History.replaceState()

 

The URLSearchParams interface defines utility methods to work with the query string of a URL. In the example below we use the following methods of this interface:

  • The has() method indicates whether a parameter with the specified name exists
  • The get() method returns the (first) value associated to the given search parameter
  • The set() method sets the value associated with a given search parameter. And very important: if the search parameter does not yet exist (which might initially be the case), this method will create the search parameter.

 

The History.replaceState() method modifies the current history entry. This method is particularly useful when you want to update the URL of the current history entry in response to some user action, e.g. the panning and zooming mentioned before.

 

And this is how it works:

If you provide the url without any parameters, you will start at the Default map view. But as you will see, the default parameters are added immediately to the address bar:

https://twiav.nl/en/arcgis/javascript/arcgis_javascript_with_uk_data_url_parameters.htm

And as soon as you start zooming and panning around, these parameters will be adjusted every time the view becomes "stationary".

 

In this way, you can zoom in to a particular spot and copy the url to make sure to share exactly that map view.

If you click on the link below you will immediately end up in Steòrnabhagh  (or Stornoway), on the island of Lewis and Harris in the Outer Hebrides:

https://twiav.nl/en/arcgis/javascript/arcgis_javascript_with_uk_data_url_parameters.htm?x=149048&y=930581&l=14 

 

Happy coding!

 

The code

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>ArcGIS JavaScript with UK data - URL Parameters: x, y and zoomlevel</title>
  <link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/css/main.css">
  <script src="https://js.arcgis.com/4.15/"></script>
  <style>
    html, body, #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <script> 
      require([
        "esri/Map",
        "esri/geometry/Point",
        "esri/views/MapView",
        "esri/widgets/Home",
        "esri/Viewpoint",
        "esri/core/watchUtils"
      ], function(Map, Point, MapView, Home, Viewpoint, watchUtils) {

      var sr = 27700;
      var xCoordHome = 500000;
      var yCoordHome = 500000;
      var zoomLevelHome = 7;
      var scaleHome = 5000000;

      var xCoord = xCoordHome;
      var yCoord = yCoordHome;
      var zoomLevel = zoomLevelHome;

      if ('URLSearchParams' in window) { // Feature detection (URLSearchParams is not supported by Internet Explorer)
        var url = new URL(document.URL);
        var search_params = url.searchParams;
        // get searchparams if x, y and l are provided in url
        if(search_params.has('x') && search_params.has('y') && search_params.has('l')) {
          var xCoord = parseInt(search_params.get('x'));
          var yCoord = parseInt(search_params.get('y'));
          var zoomLevel = parseInt(search_params.get('l'));
        }
      };

      var map = new Map({
        basemap: {
          portalItem: {
            id: "0bd3a4a6fd674a90a7d0a9e5f36fb59b" // OS Open Carto
          }
        }
      });

      var view = new MapView({
        spatialReference: sr,
        container: "viewDiv",
        map: map,
        center: new Point({x: xCoord, y: yCoord, spatialReference: sr}),
        zoom: zoomLevel
      });

      var home = new Home({
        view: view,
        // viewpoint of home needs to be defined (hard coded) because otherwise this home depends on the x, y and l values in the searchparams
        viewpoint: new Viewpoint({targetGeometry: new Point({x: xCoordHome, y: yCoordHome, spatialReference: sr}), scale: scaleHome})
      });

      view.ui.add(home, "top-left")

      watchUtils.whenTrue(view, "stationary", function() {
        modifySearchParams();
      });

      //modify url with new coords and zoomlevel as searchparams
      function modifySearchParams() {
        if ('URLSearchParams' in window) { // Feature detection (URLSearchParams is not supported by Internet Explorer)
          xCoordNew = parseInt(view.center.x);
          yCoordNew = parseInt(view.center.y);
          zoomLevelNew = view.zoom;
          search_params.set('x', xCoordNew);
          search_params.set('y', yCoordNew);
          search_params.set('l', zoomLevelNew);
          url.search = search_params.toString(); // change the search property of the main url
          new_url = url.toString(); // the new url string
          history.replaceState(null, '', new_url);
        }
      }
    });
  </script>

</head>
<body>
  <div id="viewDiv"></div>
</body>
</html>

Outcomes