Home > Back-end >  Toggle polygons multiple times is not working
Toggle polygons multiple times is not working

Time:11-15

We are using following code and toggling polygons. If we click multiple times this is not working. From fourth time this is getting drawn again and again and the shape becomes white. Please help.

We are storing polygon coordinates in a hidden textbox and passing them to the function ‘displaypolygons’. Actually we will be having more polygons and they will come from DB. In this sample code we have shown only one. Here 142 is the incremental value which incremented using loop.

<input type="checkbox" name="cb_142" id="cb_142" onclick="javascript:displaypolygons('142')"> <input type="hidden" name="latlon_142" id="latlon_142" value="(11.050885924877363,77.04118423201588),(11.050885924877363,77.04342655875233),(11.048769408381661,77.04341582991627),(11.049074777375772,77.04037956931141)"> <input type="hidden" name="area_142" id="area_142" value="A Area">

Here we are pushing the polygon coordinates to ‘gpolygons’ global array. Here we are assigning unique id using the incremental value.

<script>
function displaypolygons(ai) {
        var sel_latlon= document.getElementById("latlon_" ai).value;
        document.getElementById("coords").value = sel_latlon;
        var sel_latlon = sel_latlon.replaceAll("(", "");
        var latlon = sel_latlon.split("),");
        var mid = parseInt(latlon.length/2); var cent = latlon[mid].split(","); 
        var peditable = false; 

        var cbchecked = $('#cb_'   ai).is(":checked")
        if (!cbchecked) return togglePolygon(ai);
        
        //if (ai==3) peditable = true;
        
        const triangleCoords = []; //var idx =0;
        for(var i=0; i<latlon.length; i  ){ 
          var arr = latlon[i].split(",");
          triangleCoords.push(new google.maps.LatLng({lat: parseFloat(arr[0]), lng: parseFloat(arr[1])}, true));
        } 
     
        bounds = new google.maps.LatLngBounds();
        for (i = 0; i < triangleCoords.length; i  ) {
        bounds.extend(triangleCoords[i]);
        }
        
        // Construct the polygon.
        bermudaTriangle = new google.maps.Polygon({
          _uniqueId: ai,    
          paths: triangleCoords,
          strokeWeight: 2,
          fillOpacity: 0.45,
          fillColor: '#ffffff',
          strokeColor: '#ffffff',
          editable:peditable,
          draggable:false
        });
        bermudaTriangle.setMap(map);
        gpolygons.push(bermudaTriangle);
        
        map.setCenter(new google.maps.LatLng(bounds.getCenter()), 4);
        var area_lbl= document.getElementById("area_" ai).value;

        var mapLabel = new MapLabel({
            text: area_lbl " (Id: " ai " )",
            position: new google.maps.LatLng(bounds.getCenter()),
            map: map,
            fontSize: 14,
            align: 'center'
        });
        labelObjects.push(mapLabel);
};

google.maps.event.addDomListener(window,"load", initMap);
</script>

Then using toggle function we are toggling the polygons. We are looping through the ‘gpolygons’ array and based on the matching unique id we are displaying /hiding

<script>
function togglePolygon(id) {
  for (var i = 0; i < gpolygons.length; i  ) {
    if (gpolygons[i]._uniqueId == id) {
      if (gpolygons[i].getMap() != null) {
        gpolygons[i].setMap(null);
      } else {
        gpolygons[i].setMap(map);
      }
      
      labelObjects[i].setMap((labelObjects[i].getMap())?null:mymap)
    }
  }
  
}
</script>

CodePudding user response:

Rather than looping through all polygons stored in the global gpolygons array - if that were an Object Literal instead you could very quickly access the individual polygon references. That global could store both the polygon and the MapLabel references using a common ID - namely that of the input elements ( ie:cb_142 etc )

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Google Maps: Toggle Polygons...</title>
        <style>
            body{
                padding:0;
                margin:0;
                width:100%;
                height:100vh;
            }
            #map{
                width:100%;
                height:600px;
            }
        </style>
    </head>
    <body>
        <div id='map'></div>
        <form name='poly'>
        
            <input type='text' id='coords' />
            
            <!-- more before -->
            
            <input class='cbarea' type='checkbox' name='cb' data-id=142 />
            <input type='hidden' name='area'  data-id=142 value='A Area' />
            <input type='hidden' name='latlon'  data-id=142 value='
                (11.050885924877363,77.04118423201588),
                (11.050885924877363,77.04342655875233),
                (11.048769408381661,77.04341582991627),
                (11.049074777375772,77.04037956931141)' 
            />
            
            <input class='cbarea' type='checkbox' name='cb' data-id=143 />
            <input type='hidden' name='area'  data-id=143 value='B Area' />
            <input type='hidden' name='latlon'  data-id=143 value='
                (11.060885924877363,77.05118423201588),
                (11.060885924877363,77.05342655875233),
                (11.068769408381661,77.05341582991627),
                (11.069074777375772,77.05037956931141)' 
            />
            
            <input class='cbarea' type='checkbox' name='cb' data-id=144 />
            <input type='hidden' name='area'  data-id=144 value='C Area' />
            <input type='hidden' name='latlon'  data-id=144 value='
                (11.070885924877363,77.06118423201588),
                (11.070885924877363,77.06342655875233),
                (11.078769408381661,77.06341582991627),
                (11.079074777375772,77.06037956931141)' 
            />
            
            <!-- and repeat for all others -->
            
            
        </form>
        <script>
            const d=document;
            
            class MapLabel{// no idea what this is....
                constructor(args){
                    return Object.assign({
                    
                    },args);
                }
            }
            
            
            
            function initMap(){
            
                let polygons={
                    polys:{},
                    labels:{}
                };
                let coords=d.querySelector('#coords');
                
                const map = new google.maps.Map( document.querySelector('div#map'), {
                    zoom: 3,
                    center: { lat:0, lng:0 }
                });
                
                d.forms.poly.addEventListener('change',e=>{
                    if( e.target instanceof HTMLInputElement && e.target.type=='checkbox' ){
                        
                        
                        let id=e.target.dataset.id;
                        let area=d.querySelector(`input[name="area"][data-id="${id}"]`);
                        let latlon=d.querySelector(`input[name="latlon"][data-id="${id}"]`);
                        
                        coords.value=latlon.value;
                        
                        if( !polygons.polys.hasOwnProperty( id ) ){
                            let path=[];
                            let bounds = new google.maps.LatLngBounds();
                            
                            let pairs=latlon.value.replace(/[\(\)\t]/g,'').trim().split(',');
                            for( let i=0; i < pairs.length; i =2 ){
                                let lat=pairs[i];
                                let lng=pairs[i 1];
                                let latlng=new google.maps.LatLng(lat,lng);
                                
                                path.push( latlng );
                                bounds.extend( latlng );
                            }
                            
                            // only green so that it is easily visible!!!
                            let poly=new google.maps.Polygon({
                                _uniqueId: id,    
                                paths: path,
                                strokeWeight: 2,
                                fillOpacity: 0.45,
                                fillColor: '#00ff00',
                                strokeColor: '#000000',
                                editable:e.target.checked,
                                draggable:false
                            });
                            
                            let label=new MapLabel({
                                text: `area_lbl ( Id: ${id} )`,
                                position: new google.maps.LatLng( bounds.getCenter() ),
                                map: map,
                                fontSize: 14,
                                align: 'center'
                            });
                            
                            poly.setMap( map );     
                            
                            polygons.polys[ id ]=poly;
                            polygons.labels[ id ]=label;
                            
                            map.fitBounds( bounds );
                        }else{
                            polygons.polys[ id ].setMap( e.target.checked ? map : null  );
                            //polygons.labels[ id ].setMap( e.target.checked ? map : null );
                        }
                    }
                })
            }
        </script>
        <script async defer src='//maps.googleapis.com/maps/api/js?key=KEY&callback=initMap'></script>
    </body>
</html>

Proof of concept

CodePudding user response:

Found the fix. Need to change the togglePolygon function as

function togglePolygon(id) {
  for (var i = 0; i < gpolygons.length; i  ) {
    if (gpolygons[i]._uniqueId == id) {
      if (gpolygons[i].getMap()) {
        gpolygons[i].setMap(null);
        labelObjects[i].setMap(null);
        return;
      }     
    }
  } 
}
  • Related