azurevue.jsazure-maps

Black flash issue when toggle the visibility of symbol pin on azure map


So, I created a Vue project and added the azure-maps-control

npm install azure-maps-control

added the css in main.ts

import "azure-maps-control/dist/atlas.min.css";

Now, this is how I load the pins once map is ready

const labelId = 'label-'+r.pinname;
await map?.imageSprite.add(labelId, icons.Label.replace("{stroke}", r.pincolor));
await map?.imageSprite.createFromTemplate(r.pinname, 'marker-thick', r.pincolor, '#fff');
const stops = r.stops.map(m => m.coordinates);
stops.forEach(coord => {
  var dataSource = new atlas.source.DataSource();
  map?.sources.add(dataSource);

  var shape = new atlas.Shape(new atlas.data.Point(coord), r.pinname);
  dataSource.add(shape);

  const symbolLayerLabel = new atlas.layer.SymbolLayer(dataSource, '', {
    iconOptions: {
      image: labelId,
      allowOverlap: true,
      ignorePlacement: true
    },
  });
  map?.layers.add(symbolLayerLabel);

  const symbolLayer = new atlas.layer.SymbolLayer(dataSource, '', {
    iconOptions: {
      image: r.pinname,
      allowOverlap: true,
      ignorePlacement: true
    },
    textOptions: {
      allowOverlap: true,
      ignorePlacement: true,
      anchor: 'top',
      textField: r.pinname,
      offset: [0, -3.9],
      size: 13
    }
  });
  map?.layers.add(symbolLayer);

  dataSources.value.push(dataSource);
  symbolLayers.value.push(symbolLayer);
});

Then I created a function to toggle the visibility of that pins

symbolLayers.value.forEach(layer => {
  const opts = layer.getOptions() as LayerOptions;
  if (opts.iconOptions.image==pinname) {
    layer.setOptions({visible: visible});
    return;
  }
});

So there's a click button on the top left of this screenshot where I use the function for toggle the visibility of pins.

enter image description here

Did I miss anything?


Solution

  • Black flash issue when toggle the visibility of symbol pin on azure map

    The black flash occurs because adding/removing or manipulating layers at scale triggers frequent redraws or re-renders of the map.

    You are creating a new DataSource for every pin and two SymbolLayers per pin (one for label and one for the marker), which adds complexity and rendering overhead.

    Group all pins under a single DataSource.

    Revised code:

    const dataSource = new atlas.source.DataSource();
    map?.sources.add(dataSource);
    
    // Add all pins to a single DataSource
    r.stops.forEach(coord => {
      const shape = new atlas.Shape(new atlas.data.Point(coord), {
        id: r.pinname,
        labelColor: r.pincolor,
        iconColor: r.pincolor
      });
      dataSource.add(shape);
    });
    
    // Add SymbolLayer for icons
    const symbolLayer = new atlas.layer.SymbolLayer(dataSource, null, {
      iconOptions: {
        image: 'marker-thick',
        allowOverlap: true,
        ignorePlacement: true
      }
    });
    map?.layers.add(symbolLayer);
    
    // Add SymbolLayer for labels
    const symbolLayerLabel = new atlas.layer.SymbolLayer(dataSource, null, {
      textOptions: {
        textField: ['get', 'id'],
        anchor: 'top',
        offset: [0, -3.9],
        size: 13
      },
      iconOptions: {
        allowOverlap: true,
        ignorePlacement: true
      }
    });
    map?.layers.add(symbolLayerLabel);
    
    // Toggle visibility function
    function togglePinVisibility(pinname: string, visible: boolean) {
      const filter = visible
        ? ['==', ['get', 'id'], pinname] // Show specific pin
        : ['!=', ['get', 'id'], pinname]; // Hide specific pin
    
      symbolLayer.setOptions({ filter });
      symbolLayerLabel.setOptions({ filter });
    }
    

    If you want to toggle visibility for specific pins, use the filter property to hide/show pins by their ID.

    symbolLayer.setOptions({
      filter: visible ? ['==', ['get', 'id'], pinname] : ['!=', ['get', 'id'], pinname]
    });
    
    symbolLayerLabel.setOptions({
      filter: visible ? ['==', ['get', 'id'], pinname] : ['!=', ['get', 'id'], pinname]
    });
    

    Result:

    enter image description here