How do I select which basemap is selected in the gallery AT STARTUP?

6609
12
07-24-2015 10:19 AM
ericliprandi
New Contributor III

Here is our situation:

  • users can have a custom list of basemaps
  • we use the BasemapGallery to allow them to select their basemap
  • we persist the basemap id in a cookie to load that same basemap the next time they visit their app

At this point what is the official way to load the Basemap gallery against a map with a specific basemap selected?

The only 2 lines of code involved in setting up the gallery with the map are:

var gallery = new BasemapGallery( options );
gallery.startup();

As far as we can tell, there is nothing in the options that allows this. We don't see a selected property on the Basemap.

So far, our only option is to let it load the gallery, using the first basemap, then, as soon as it's loaded, call select(id) on the gallery. But as you can guess, the experience is horrible at best. The map loads first with a basemap and within a second or two switches to the one the user really wanted.

Tags (1)
0 Kudos
12 Replies
ChrisSmith7
Frequent Contributor

Eric,

Off top hand, I'm not sure... I would need to dig a bit to see if there are any options. However, I wanted to share a technique I employ for a similar scenario.

We have a bit of stuff that runs in the background that causes rendering artifacts to manifest on the front-end. Really, we could probably adjust the timing of events and that would probably prevent the artifacts, but I implemented a workaround by calling a dojo standby - dojox.widget.Standby — The Dojo Toolkit - Reference Guide - then fading-in the map container after all pre-processing completes. So, the user simply sees a spinner until the map is ready, then it fades-in. It looks pretty slick... you could call your fade-in routine and dismiss the spinner after the persisted basemap loads.

This still seems like a kludge, just less kludgey!

ericliprandi
New Contributor III

Chris, yeah that was the route we were heading down too. We are primarily an AngularJS app and were going to use their animations and all to do what you suggest: wait for us to know the map is ready for interaction, hide it until then.

There are other implications though of setting a "random" basemap first and then select the one you want. in particular, I believe our customers have reported issues with LODs not updating as you switch basemaps.

0 Kudos
thejuskambi
Occasional Contributor III

Hello eric,

There are a couple of way you can do this.

if you are creating the custom list in esriBasemaps as shown here esri/basemaps | API Reference | ArcGIS API for JavaScript then you can set basemap you want while initializing the map itself.

otherwise, you could save your custom as json string instead of just saving the name and then pass while initializing the map. Once the map is loaded you can use select(id) to sync the map and BasemapGallery.

ericliprandi
New Contributor III

thejus,

I am not sure I understand your suggestion(s). Let me see if I can clarify:

We are an ISV, so our customers want a fair bit of flexibility in specifying their list of basemaps. Because we are an Esri partner, we are frequently pushed to make use of the ArcGIS Basemaps (from ArcGIS.com) even though most of our real customers don't use them. It apparently looks good when we demo and Esri personnel is in the room.

That being said, we allow them to use the showArcGISBasemaps option. When they do that, I can't see a way to control order or anything. It always loads the first one in the list (Imagery right now I think). It does that as soon as the gallery is built.

I am not sure what you are referring to as "save your custom as json string". I know how to build my own list of basemaps (at least I think I do). I use the Basemap and BasemapLayer with the proper set of id, type, etc., build an array and pass that to the constructor.

However, I have the same problem with that: as soon as I provide the list to the gallery (as the constructor parameter), it will automatically select the first one and apply to the map. After which, I have to wait "a little bit" and I can then call select(id) on the gallery.

Thanks for helping and please let me know I misunderstood anything.

0 Kudos
RichRuh
Esri Regular Contributor

Although utilities will often not use Esri-provided basemaps, they are free to create their own from their own proprietary sources of data.

thejuskambi
Occasional Contributor III

see the example I had added a link. In the below case a custom basemap is created first and then map is initialized with that custom basemap.

require([
    "esri/basemaps",
    "esri/map",
    "dojo/domReady!"
  ], function (esriBasemaps, Map){
    esriBasemaps.delorme = {
      baseMapLayers: [{url: "http://services.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer"}
      ],
      thumbnailUrl: "http://servername.fqdn.suffix/images/thumbnail_2014-11-25_61051.png",
      title: "Delorme"
    };
    var map = new Map("ui-map", {
      basemap: "delorme",
      center: [-111.879655861, 40.571338776], // long, lat
      zoom: 13,
      sliderStyle: "small"
    });
});

again in the above example you can see that the basemap is kind of converted to json string. I was asking you to save that string.

I have not seen the behavior you are saying just because you are initializing BasemapGallery, the map should not be affected by it. Can you share the code. Robert Scheitlin, GISP​ can you please confirm if that is an expected behavior.

RobertScheitlin__GISP
MVP Emeritus

Eric,

  The first basemap in the basemaps array is always the selected base map (unless you use showArcGISBasemaps). So if you need a different on selected initially when your app starts up then all you have to do is re-order your basemap array before your startup the basemap gallery widget. The issue you will run into is if you choose to use the arcgis base maps and what a specific basemap selected first then you will have to manually add the arcgis basemaps to the basemap array and NOT use "showArcGISBasemaps".

Here is a sample that shows how to manually load the ArcGISBasemaps and some comments in the code that tell you how to make a specific basemap the first selected basemap:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!--The viewport meta tag is used to improve the presentation and behavior of the samples
    on iOS devices-->
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
  <title></title>

  <link rel="stylesheet" href="http://js.arcgis.com/3.14/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.14/esri/css/esri.css">
  <style>
    html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    #map{
      padding:0;
    }
  </style>

  <script src="http://js.arcgis.com/3.14/"></script>
  <script>
    var map;
    require([
      "esri/map", "esri/dijit/BasemapGallery", "esri/arcgis/utils",
      "dojo/parser", "esri/dijit/BasemapLayer", "esri/dijit/Basemap",
      "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dijit/TitlePane",
      "dojo/domReady!"
    ], function(
      Map, BasemapGallery, arcgisUtils,
      parser, BasemapLayer, Basemap
    ) {
      parser.parse();

      map = new Map("map");

      var basemaps = [];

      var imgeryLayer = new BasemapLayer({
        url: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
      });
      var ImageryBasemap = new Basemap({
        layers: [imgeryLayer],
        title: "Imagery",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/86de95d4e0244cba80f0fa2c9403a7b2/info/thumbnail/tem..."
      });

      var imgLayer = new BasemapLayer({
        url: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
      });
      var imgLayer2 = new BasemapLayer({
        url: "http://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer"
      });
      var ImagerywLblBasemap = new Basemap({
        layers: [imgLayer, imgLayer2],
        title: "Imagery with Labels",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/413fd05bbd7342f5991d5ec96f4f8b18/info/thumbnail/ima..."
      });

      var streetsLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
      });
      var StreetsBasemap = new Basemap({
        layers: [streetsLayer],
        title: "Streets",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/d8855ee4d3d74413babfb0f41203b168/info/thumbnail/wor..."
      });

      var topoLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"
      });
      var TopoBasemap = new Basemap({
        layers: [topoLayer],
        title: "Topographic",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/6e03e8c26aad4b9c92a87c1063ddb0e3/info/thumbnail/top..."
      });

      var dgLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer"
      });
      var dgLayer2 = new BasemapLayer({
        url: "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Reference/MapServer"
      });
      var DGBasemap = new Basemap({
        layers: [dgLayer, dgLayer2],
        title: "Dark Gray Canvas",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/25869b8718c0419db87dad07de5b02d8/info/thumbnail/DGC..."
      });

      var lgLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"
      });
      var lgLayer2 = new BasemapLayer({
        url: "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Light_Gray_Reference/MapServer"
      });
      var LGBasemap = new Basemap({
        layers: [lgLayer, lgLayer2],
        title: "Light Gray Canvas",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/8b3b470883a744aeb60e5fff0a319ce7/info/thumbnail/lig..."
      });

      var natgeoLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"
      });
      var natgeoBasemap = new Basemap({
        layers: [natgeoLayer],
        title: "National Geographic",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/509e2d6b034246d692a461724ae2d62c/info/thumbnail/nat..."
      });

      var oLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer"
      });
      var oLayer2 = new BasemapLayer({
        url: "http://services.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer"
      });
      var OceanBasemap = new Basemap({
        layers: [oLayer, oLayer2],
        title: "Oceans",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/48b8cec7ebf04b5fbdcaf70d09daff21/info/thumbnail/tem..."
      });

      var terrLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer"
      });
      var terrLayer2 = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Reference_Overlay/MapServer"
      });
      var TerrBasemap = new Basemap({
        layers: [terrLayer, terrLayer2],
        title: "Terrain with Labels",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/aab054ab883c4a4094c72e949566ad40/info/thumbnail/ter..."
      });

      var osmLayer = new BasemapLayer({
        type: "OpenStreetMap"
      });
      var osmBasemap = new Basemap({
        layers: [osmLayer],
        title: "OpenStreetMap",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/5d2bfa736f8448b3a1708e1f6be23eed/info/thumbnail/tem..."
      });

      var usatopoLayer = new BasemapLayer({
        url: "http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer"
      });
      var usaTopoBasemap = new Basemap({
        layers: [usatopoLayer],
        title: "USA Topo Maps",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/931d892ac7a843d7ba29d085e0433465/info/thumbnail/usa..."
      });

      var USGSNatMapLayer = new BasemapLayer({
        url: "http://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer"
      });
      var USGSNatMapBasemap = new Basemap({
        layers: [USGSNatMapLayer],
        title: "USGS National Map",
        thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/6d9fa6d159ae4a1f80b9e296ed300767/info/thumbnail/nat..."
      });

      /*This is the standard order of the ArcGISBasemaps*/
      /*If you want to set a specific basemap as the first selected basemap
        then just move it to the first position in the array*/
      basemaps.push(ImageryBasemap);
      basemaps.push(ImagerywLblBasemap);
      basemaps.push(StreetsBasemap);
      basemaps.push(TopoBasemap);
      basemaps.push(DGBasemap);
      basemaps.push(LGBasemap);
      basemaps.push(natgeoBasemap);
      basemaps.push(OceanBasemap);
      basemaps.push(TerrBasemap);
      basemaps.push(osmBasemap);
      basemaps.push(usaTopoBasemap);
      basemaps.push(USGSNatMapBasemap);

      var basemapGallery = new BasemapGallery({
        showArcGISBasemaps: false,
        basemaps: basemaps,
        map: map
      }, "basemapGallery");
      basemapGallery.startup();

      basemapGallery.on("error", function(msg) {
        console.log("basemap gallery error:  ", msg);
      });
    });
  </script>
</head>

<body class="claro">
  <div data-dojo-type="dijit/layout/BorderContainer"
       data-dojo-props="design:'headline', gutters:false"
       style="width:100%;height:100%;margin:0;">

    <div id="map"
         data-dojo-type="dijit/layout/ContentPane"
         data-dojo-props="region:'center'"
         style="padding:0;">

      <div style="position:absolute; right:20px; top:10px; z-Index:999;">
        <div data-dojo-type="dijit/TitlePane"
             data-dojo-props="title:'Switch Basemap', closable:false, open:false">
          <div data-dojo-type="dijit/layout/ContentPane" style="width:380px; height:280px; overflow:auto;">
            <div id="basemapGallery"></div>
          </div>
        </div>
      </div>

    </div>
  </div>
</body>

</html>
ericliprandi
New Contributor III

Thejus,

Thanks for the reply. This was looking promising. Unfortunately, with this technique, Bing maps do not appear to be supported. I tried setting the type property on the layer and it does not take it. It works great for OpenStreetMap, but no luck for Bing

    require(['dojo/ready',
      'esri/basemaps',
      'esri/map'
    ], function(ready, basemaps, Map) {
      ready(function() {
        var custom = {
          title: "Eric Map",
          thumbnailUrl: "http://js.arcgis.com/3.14/esri/images/basemap/streets.jpg",
          baseMapLayers: [{
            type: 'OpenStreetMap'
               // type: 'BingMapsAerial' does not work
          }]
        };
        basemaps.custom = custom;


        // map
        var map = new Map('map', {
          basemap: 'custom'
        });
      });
    });

I assume the type value is the same used by the Basemap.

Regards,

Eric.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Eric,

  Bing basemaps definitely works when you set the bingMapsKey in the BasemapGallery constructor.

      var basemapGallery = new BasemapGallery({
        showArcGISBasemaps: false,
        basemaps: basemaps,
        map: map,
        bingMapsKey: "your bing key"
      }, "basemapGallery");
      basemapGallery.startup();

      var BingHybridLayer = new BasemapLayer({
        type: "BingMapsHybrid"
      });
      var BingHyBasemap = new Basemap({
        layers: [BingHybridLayer],
        title: "Bing Hybrid",
        thumbnailUrl: "http://calhoun.maps.arcgis.com/sharing/rest/content/items/10a7e8fdb0fe4e869659d1bc4cc0be7d/info/thum..."
      });
      basemaps.push(BingHyBasemap);
0 Kudos