Pergunta

I am trying to keep my basemap layer opacity at a constant between different selections (and can be controlled by the user with a slider). Any basemap layers that don't have a related 'reference' layer behave as expected (i.e. if topo is at 25% before changing to imagery, it will update to 25% on change). If a user selects a basemap that also has a reference layer (imagery with labels; light gray canvas, etc), the reference layer ignores the opacity setting when loaded and will only change AFTER the user tries to move the slider. Thoughts?

Fun tidbit... Basemap layer 'Terrain with Labels' ignores this completely on both the imagery and the text when swapping. It almost looks like it refreshes after it loads.

Here is the working example in JSFiddle (http://jsfiddle.net/disuse/ez6mN/) and the dojo code that I am using to replicate my issue. Using the latest Esri ArcGIS Javascript 3.7.

Codeblock

var baseMap_Opacity;
var baseOpacity = 0.25;

require([
    "esri/map", 
    "esri/dijit/BasemapGallery",
    "dijit/form/HorizontalSlider",
    "dijit/form/HorizontalRule",
    "dijit/form/HorizontalRuleLabels",
    "dojo/parser",
    "dojo/dom",   
    "dojo/on", 
    "dojo/ready",
    "dojo/domReady!"
], function(
    Map,
    BasemapGallery,
    HorizontalSlider, 
    HorizontalRule, 
    HorizontalRuleLabels,
    parser,
    dom,
    on,
    ready
) {
ready(function() {
    map = new Map("map", {
        center: [-121.569, 39.00],
        zoom: 7,
        optimizePanAnimation: true,
        basemap: "topo"
    });
    var basemapGallery = new BasemapGallery({
      showArcGISBasemaps: true,
      map: map
    }, "basemaps");
    basemapGallery.startup(); 

    basemap = map.getLayer("layer0");
    basemap.setOpacity(baseOpacity);

    on(basemapGallery, "selection-change", function() {
       changeBasemapOpacity(baseOpacity); 
    });

    createHorzSlider();
});    

function createHorzSlider() {
    baseMap_Opacity = dom.byId("baseMap_Opacity");
    baseMap_Opacity.innerHTML = Math.round(baseOpacity*100) + "%";

    var horzSlider = new HorizontalSlider({
        minimum: 0,
        maximum: 1,
        value: baseOpacity,
        intermediateChanges: true,
        showButtons: true,
        discreteValues: 101,
        style: "width: 300px; margin-left: 25px;",
        onChange: function(value) {
            changeBasemapOpacity(value);
        }

    }, "horzSlider");    
    horzSlider.startup();   

    var horzSliderRule = new HorizontalRule({
       container: "bottomDecoration",
       count: 2 ,
       style: "height: 5px; width: 288px; margin-top: 5px; margin-left: 32px;"
    }, "horzSliderRule");
    horzSliderRule.startup();

    var horzSliderLabels = new HorizontalRuleLabels({
       container: "bottomDecoration",
       labels: ["0", "100"],
       style: "width: 288px; margin-left: 32px;",
       labelStyle: "font-style: normal; font-weight: bold; font-size: 14px;"
    }, "horzSliderLabels");
    horzSliderLabels.startup();
}  
function changeBasemapOpacity(value) {
    baseOpacity = value;
    baseMap_Opacity.innerHTML = Math.round(baseOpacity*100) + "%";

    var esriURL = "http://services.arcgisonline.com";

    var layers = map.getLayersVisibleAtScale();

    for (var i = 0; i < layers.length; i++) {
        var lyr = map.getLayer(layers[i].id);
        if ((lyr._basemapGalleryLayerType) || (lyr.id == "layer0") || ((lyr.url) && (lyr.url.indexOf(esriURL) == 0))) {
            lyr.setOpacity(baseOpacity);
        }    
    }

}    
});
Foi útil?

Solução

The basemap gallery's selection-change event fires after the newly selected basemap is in the map. This fires before reference layers are added and is the intended design, the idea being that you wouldn't want to manipulate reference layers. In your case, that's not what you want so using selection-change is out.

To accomplish what you want, use the map's layer-add-result event and check if layer._basemapGalleryLayerType is truthy. If it is, you know a layer used by the basemap gallery was added to the map and you should update its opacity. Here's a code snippet:

map.on("layer-add-result", function(e) {
    if ( e.layer._basemapGalleryLayerType ) {
        e.layer.setOpacity(baseOpacity);
    }
});

Regarding the issue with the Terrain with Labels basemap, things are working as expected. Because that basemap's reference layer includes labels as well as political boundaries and major roads, it looks like opacity isn't being applied when in fact it is. Using the code above will set opacity on both the layer that represents the terrain basemap as well as the reference layer.

Here's a modified version of your page that I think accomplishes what you want: http://jsbin.com/IyixAPa/1/edit

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top