ThinkGeo.com    |     Blog    |     Wiki    |     Support

Preventing labels from showing at certain zoom levels?

Is there a way to prevent labels from showing up at certain zoom levels? Some users don’t want to see labels when zoomed out far (while others want them always visible). I tried setting the .IsActive property ZoomLevels, but it doesn’t seem to work.

I am using CustomZoomLevels for the map itself.

Hi Dan,

I think the code as below is helpful for your scenario.

            ZoomLevel customZoomLevel1 = new ZoomLevel(500000);
        customZoomLevel1.DefaultPointStyle = PointStyles.Capital1;
        customZoomLevel1.DefaultTextStyle = TextStyles.Capital1("Label");

        ZoomLevel customZoomLevel2 = new ZoomLevel(250000);
        customZoomLevel2.DefaultPointStyle = PointStyles.Capital1;

        map.ZoomLevelSet.CustomZoomLevels.Add(customZoomLevel1);
        map.ZoomLevelSet.CustomZoomLevels.Add(customZoomLevel2);

If you are using CustomZoomLevels, please don’t set default style or custom style for zoomlevel 01 to 20.

Regards,

Ethan

I’m a little confused. So JUST my map object has custom zoom levels, not the layers themselves. The layer’s customzoomlevels has 0 in the collection.

Let’s say I want to have labels only appear past zoom level 5.

Right now I’m doing looping through the zoom levels in the layer, setting .IsActive to false if it’s before zoom level 5, or true if after.

This tends to make the entire layer disappear from the map for some reason.

I tried setting ApplyUntilZoomLevel.None thinking maybe that being set previously was preventing the other zoomlevel styles from activating. But that didn’t change anything either.

Hi Dan,

The custom levels for map is only works for map, it mainly control the zoomlevels.

The custom levels for layer is control which scale the layer will be drawn.

If you set custom zoomlevels for map, and you want to control some levels don’t shows this layer, you should want to set the same custom zoomlevels for this layer also.

The sample code as below:

        private void map_Loaded(object sender, RoutedEventArgs e)
    {
        map.MapUnit = GeographyUnit.DecimalDegree;


        map.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(1690591790));
        map.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(1095295895));
        map.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(127647947));
        map.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(53823973));

        LayerOverlay layerOverlay = new LayerOverlay();
        ShapeFileFeatureLayer shapeFileLayer = new ShapeFileFeatureLayer(@"..\..\AppData\states.shp");
        ZoomLevel level1 = new ZoomLevel(1690591790);
        level1.DefaultAreaStyle = WorldStreetsAreaStyles.Military();

        shapeFileLayer.ZoomLevelSet.CustomZoomLevels.Add(level1);
        shapeFileLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(1095295895));
        shapeFileLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(127647947));

        ZoomLevel level4 = new ZoomLevel(53823973);
        level4.DefaultAreaStyle = WorldStreetsAreaStyles.Military();            
        shapeFileLayer.ZoomLevelSet.CustomZoomLevels.Add(level4);

        
        layerOverlay.Layers.Add(shapeFileLayer);
        map.Overlays.Add(layerOverlay);

        shapeFileLayer.Open();
        map.CurrentExtent = shapeFileLayer.GetBoundingBox();
        map.Refresh();
    }

In this sample, the layer only shows in level 1 and level 4, ApplyUntilZoomLevel don’t works for this scenario, you shoudl want to set style for each level you want to shows current layer.

Wish that’s helpful.

Regards,

EThan

Hi, I’m sending a sample project showing what I’m trying. This project uses a single shape file, which you can get from the attached zip file.

There’s a few buttons at the top of the window. The first two load the layer as either an InMemoryFeatureLayer or a ShapefileFeatureLayer. The rest of the buttons perform a certain action with the zoomlevels and textstyle.

In the comments of the related functions you’ll see what my result was after using them.

Note: You’ll have to change the filepath in the code to wherever you place the data. The places to change this are Lines 34 and 161 (in constructor of ShapeFile).

You can get the project here: https://drive.google.com/open?id=19EWP5tychdpjeanWTHZ_maHgTxoqRp5m

Test Data.zip (307.6 KB)

Remember, I’m just trying to prevent the labels from showing at certain zoom levels. I don’t want to have to create duplicate styles and set the .IsActive property for each zoomlevel.

Hi Dan,

Thanks for your project and data, I reproduced your problem and found what’s the reason of that.

The reason is the text style you set to each zoomlevel is object reference, so if you modify anyone, all the other levels will get the same result.

image

Our suggestion is:
Split shape and labels into different layers

        private void UseInMemory(object sender, RoutedEventArgs e)
    {
        (map.Overlays[0] as LayerOverlay).Layers.Clear();
        InMemoryFeatureLayer shapeLayer = CreateInMemoryLayer(); // Create shape layer
        shapeLayer.Open();
        shapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
        shapeLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = _pointStyle;

        InMemoryFeatureLayer labelLayer = CreateInMemoryLayer(); // Create label layer
        labelLayer.Open();
        TextStyle tempStyle = _textStyle.CloneDeep() as TextStyle;
        tempStyle.TextColumnName = labelLayer.FeatureSource.GetColumns()[0].ColumnName;
        ApplyTextStyles(labelLayer.ZoomLevelSet, tempStyle, 1, 20);

        (map.Overlays["MainOverlay"] as LayerOverlay).Layers.Add("layer1", shapeLayer);
        (map.Overlays["MainOverlay"] as LayerOverlay).Layers.Add("layerLabel", labelLayer);
        map.Refresh();
    }

Then you can set ZoomLevel.IsActive instead of set style.isActive. (We found a bug here, please upgrade to the latest package today to make ZoomLevel.IsActive works) Please notice, if you set ApplyUntilZoomLevel property, each scale(zoomlevel or custom zoomlevel) between this region will be drawn always, which means IsActive don’t works when the level contained by ApplyUntilZoomLevel.

So you should want use a funtion to assign style:

     private void ApplyTextStyles(ZoomLevelSet set, TextStyle style, int applyFromLevel, int applyToLevel)
    {
        int index = 1;

        foreach (ZoomLevel level in set.GetZoomLevels())
        {
            if (index >= applyFromLevel && index <= applyToLevel)
            {
                level.DefaultTextStyle = style;
            }
            index++;
        }
    }

And your code have another problem:

The layer.ZoomLevelSet.GetZoomLevels() return a new collection, which means all your changes in it won’t pass back to map. So please directly set the IsActive to zoomlevel for example: layer.ZoomLevelSet.ZoomLevel05.IsActive = false, or you can create a new ZoomLevelSet with the modified values and set it back.

The other thing you need notice is because your map don’t use the same zoomlevelset with your layer, which means the levels in map and layer is not match, so maybe one level in layer corresponding more levels when you zoom in and zoom out.

If you hadn’t upgrade the package, you can choose set style or set null for specified level, it also should works for your scenario.

Regards,

Ethan