Azure maps - (drawing module) delayed line rendering

Aidan Booker 41 Reputation points
2022-06-29T18:51:32.843+00:00

Good evening!

Following on from my last question, I am left with the issue of delayed rendering when drawing shapes.

Here's a video of it in action.

From the video, you can see that the line doesn't smoothly follow the mouse, instead it seems to delay the rendering until the mouse stops for some minimal amount of time.
This isn't a deal breaker, but be nice to have that sweet, sweet, buttery smooth following that is present in the samples.

So, here's the deal - I don't know how much is relevant to provide to get to the bottom of this (or likely I'd have figured it out myself already).

Let's start with some basics... I won't put any real effort in to altering my samples, you can probably infer the amount of wrapping I'm doing and what they're doing generally (and can ask if not).

Loading the module:

protected onInit(): void {  
    this.drawingManager = new azDrawing.drawing.DrawingManager(this.state.map, {  
        interactionType: azDrawing.drawing.DrawingInteractionType.click,  
        shapeDraggingEnabled: true,  
        shapeRotationEnabled: true,  
    });  
        this.state.map.events.add('drawingcomplete', this.drawingManager, (e: azMap.Shape) => this.onShapeCompleted(e));  
}  

Hooray, it's loaded.

I programmatically new/edit/stopping:

public new(): void {  
    // ...  
    this.drawingManager.getSource().clear();  

    this.drawingManager.setOptions({  
        mode: azDrawing.drawing.DrawingMode.drawPolygon  
    });  

    // ...  
}  

public edit(shape: azMap.Shape): void {  
    // ...  
    this.drawingManager.edit(shape);  
    // ...  
}  

public stop(save: boolean = false): void {  
    // ...  
    this.drawingManager.setOptions({  
        mode: azDrawing.drawing.DrawingMode.idle  
    });  
      
    const source = this.drawingManager.getSource();  
    if (source) {  
        const shapes = source.getShapes();  
        if (shapes && shapes.length > 0) {  
            const shape = shapes[0];  
            if (save && shape['data']) this.save(shape);  
        }  
    }  
    source?.clear();  

    // ...  
}  

The only other thing that might be affecting it is events? I have mouseover/mouseout/click events for my bubble/shape layers.
I do have a debounce timer in use for the items that I emit on all the hovering/clicking. Seeing as how I have each layer handling their own click events, I wait (50ms-ish) for all those events to come in and concat them into a single list of shapes for my component to emit, instead of like, 7...

However, I don't think this should have such an effect, it's not blocking events or methods from processing properly, it's just gathering the outputs and moving on with life. But it's a timer, and the issue feels like something is blocking it until we stop moving...

Let me know what other details you want/need to help pin this down.

Thanks.

Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
561 questions
{count} votes

1 answer

Sort by: Most helpful
  1. rbrundritt 13,696 Reputation points Microsoft Employee
    2022-06-30T16:51:14.147+00:00

    Very odd. Looks like you can only draw two points (start/end of a single line). I suspect something is blocking the click event in the drawing manager from firing which would add the point to the shape and allow for the next point in the shape to be previewed/drawn.

    A couple things to check and try:

    • Try commenting out your mouseover/mouseout/click events to see if that resolves the issue. If it does, then uncomment them one by one. This should help narrow down what we need to look into.
    • Check that your event handlers don't call the preventDefault function that's on the event argument as that will prevent the event from bubbling through to other functions in the map, like drawing tools.
    • Double check that your event handlers aren't throwing any errors. It's possible an error there could be prevent the rest of the event handlers in the stack from being fired.
    • It sounds like you have a bunch of events added to each layer that do similar things for each layer and have some custom code that aggregates these somehow. A simpler/cleaner option might be to simply add your events to the map and not the layer, then check the event arguments to see if there was a shape in the arguments, and if so, which data source the shape came from. I've added a code sample below: <!DOCTYPE html>
      <html lang="en">
      <head>
      <title></title>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
         <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />  
         <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>  
      
         <script>  
             var map, datasource1, datasource2, testDataSize = 10;  
      
             function GetMap() {  
                 //Initialize a map instance.  
                 map = new atlas.Map('myMap', {  
                     view: 'Auto',  
      
                     authOptions: {  
                         authType: 'subscriptionKey',  
                         subscriptionKey: '<Your Azure Maps Key>'  
                     }  
                 });  
      
                 //Wait until the map resources are ready.  
                 map.events.add('ready', function () {  
                  //Create two data sources, add some random points, and a connect a layer to each data source.  
                     datasource1 = new atlas.source.DataSource('Blue pin source');  
                     map.sources.add(datasource1);  
      
                     datasource1.add(generateRandomPoints(testDataSize));  
      
                  map.layers.add(new atlas.layer.BubbleLayer(datasource1));  
      
                  datasource2 = new atlas.source.DataSource('Red pin source');  
                     map.sources.add(datasource2);  
      
                     datasource2.add(generateRandomPoints(testDataSize));  
      
                     map.layers.add(new atlas.layer.BubbleLayer(datasource2, null, {  
                      color: 'red'  
                  }));  
      
                     //Add a click event to the map.   
                     map.events.add('click', function (e) {  
                      var topItem = 'map';  
      
                      if(e.shapes && e.shapes.length > 0){  
                          var topShape = e.shapes[0];  
      
                          if(topShape instanceof atlas.Shape){  
                              topItem = `Shape from data source "${topShape.dataSource.id}"`;  
                          } else {  
                              //Shape is a GeoJSON feature. Ensure the source isn't 'vectorTiles' which is the basemaps data source.  
                              if(topShape.source !== 'vectorTiles') {  
                                  topItem = `Shape from data source "${topShape.source}"`;  
                              }  
                          }  
                      }  
      
                         document.getElementById('output').innerText = `${topItem} has been clicked.`;  
                     });  
                 });  
             }  
      
             function generateRandomPoints(cnt) {  
                 var layerData = [];  
      
                 for (var i = 0; i < cnt; i++) {  
                     layerData.push(new atlas.data.Feature(new atlas.data.Point([Math.random() * 360 - 180, Math.random() * 170 - 85]), {  
                         title: 'Pin_' + i  
                     }));  
                 }  
      
                 return layerData;  
             }  
         </script>  
      
      <style>
      body, html, #myMap {
      padding: 0;
      margin: 0;
      width: 100%;
      height: 100%;
      }
      #output {  
      position: absolute;  
      top: 10px;  
      left: 10px;  
      padding: 10px;  
      background-color: white;  
      }  
      
      </style>
      </head>
      <body onload="GetMap()">
      <div id="myMap"></div>
      <div id="output"></div>  
      
      </body>
      </html>
    1 person found this answer helpful.