Convert latitude and longitude to GMS (Degrees, minutes and seconds)

Asked

Viewed 2,066 times

2

I have a project in Google Maps Javascript that involves a lot of interconnected functions. At the moment, I have 2 text inputs receiving Latitude and Longitude of my mouse click in the Google Maps map div, in each click it normally receives the coordinates, the problem is that I receive them only in decimal (ex: 30.049402, 56.055040) and would like to receive them in GMS (minutes seconds degrees) also.

At the moment I am able to show in these 2 inputs the characters of the GMS (ex: S1º2'3") but with the values in Nan.

I wanted to know what I’m doing wrong, since after a few refresh’s he can even convert correct, but just refresh the page and return to the values Nan.

My ultimate goal would be to leave the same as the existing map on the site: GPS Converter, picking up the two coordinates with the click.

Below follows the results image and the script part:

Antes de pressionar o botão "GMS" para converter

Depois de pressionar o botão "GMS" para converter

var lat = document.getElementById("latMap").value;
var lng = document.getElementById("lngMap").value;

document.getElementById('converter').addEventListener('click', function() {
    ddToDms(lat, lng);
});

// conversion string in DD to DMS.
function ddToDms(lat, lng) {
    var latResult, lngResult, dmsResult;

    lat = parseFloat(lat);
    lng = parseFloat(lng);

    latResult = (lat >= 0)? 'N' : 'S';
    // Call to getDms(lat) function for the coordinates of Latitude in DMS.
    // The result is stored in latResult variable.
    
    latResult += getDms(lat);
    lngResult = (lng >= 0)? 'L' : 'O';
    
    // Call to getDms(lng) function for the coordinates of Longitude in DMS.
    // The result is stored in lngResult variable.
    lngResult += getDms(lng);

    document.getElementById("latMap").value = latResult;
    document.getElementById("lngMap").value = lngResult;
}



function getDms(val) {
    var valDeg, valMin, valSec, result;

    val = Math.abs(val);

    valDeg = Math.floor(val);
    result = valDeg + "º";

    valMin = Math.floor((val - valDeg) * 60);
    result += valMin + "'";

    valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000) / 1000;
    result += valSec + '"';

    return result;
}
<div id="row" class="row">
    <div class="col-md-12">
        <label for="name"><h1 id="title">Latitude:</h1></label></font>
        <input id="latMap" class="form-control"/>
    </div>

    <div class="col-md-12">
        <br>
          <label for="name"><h1 id="title">Longitude:</h1></label>
          <input id="lngMap" class="form-control" />
    </div>
</div>

<button id="converter" class="btn btn-primary">
    <i class="fas fa-redo-alt"></i> GMS
</button>

UPDATE: Below the complete project script.

  <!-- script da função do google maps api !-->
    <script>

    /* Variaveis do mapa e alternar entre matriz\filial */
    var matriz = {lat: -30.967885713671667, lng: -54.67343294672901, zoom:21};
    var filial = {lat: -30.975773, lng:-54.643425, zoom:18};
    var map;
    var initMap;

        // Função de centralizar
        function CenterControl(controlDiv, map) {

        // Setar CSS para as bordas do painel
        var controlUI = document.createElement('div');
        controlUI.style.backgroundColor = '#fff';
        controlUI.style.border = '2px solid #fff';
        controlUI.style.borderRadius = '3px';
        controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
        controlUI.style.cursor = 'pointer';
        controlUI.style.marginBottom = '22px';
        controlUI.style.textAlign = 'center';
        controlUI.title = 'Clique para ir para a Matriz';
        controlDiv.appendChild(controlUI);

        // Setar CSS para o interior do painel
        var controlText = document.createElement('div');
        controlText.style.color = 'rgb(25,25,25)';
        controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
        controlText.style.fontSize = '16px';
        controlText.style.lineHeight = '38px';
        controlText.style.paddingLeft = '5px';
        controlText.style.paddingRight = '5px';
        controlText.innerHTML = 'Matriz';
        controlUI.appendChild(controlText);


        // Função do click para alternar foco para a matriz
        controlUI.addEventListener('click', function() {
          map.setCenter(matriz);
        });

      }

      // Função para centralizar mapa 2
      function CenterControl2(controlDiv2, map) {

          // Setar CSS para as bordas do painel
          var controlUI2 = document.createElement('div2');
          controlUI2.style.backgroundColor = '#fff';
          controlUI2.style.border = '14px solid #fff';
          controlUI2.style.borderRadius = '3px';
          controlUI2.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
          controlUI2.style.cursor = 'pointer';
          controlUI2.style.marginBottom = '22px';
          controlUI2.style.marginLeft = '7px';
          controlUI2.style.textAlign = 'center';
          controlUI2.title = 'Clique para ir para a Filial';
          controlDiv2.appendChild(controlUI2);

          // Setar CSS para o interior do painel
          var controlText2 = document.createElement('div2');
          controlText2.style.color = 'rgb(25,25,25)';
          controlText2.style.fontFamily = 'Roboto,Arial,sans-serif';
          controlText2.style.fontSize = '16px';
          controlText2.style.lineHeight = '38px';
          controlText2.style.paddingLeft = '5px';
          controlText2.style.paddingRight = '5px';
          controlText2.style.padding = '50px 0px 0px 0px';
          controlText2.innerHTML = 'Filial';
          controlUI2.appendChild(controlText2);

          // Função para centralizar mapa na Filial
          controlUI2.addEventListener('click', function() {
            map.setCenter(filial);
          });
        }

      var customLabel = {
        restaurant: {
          label: 'R'
        },
        bar: {
          label: 'B'
        }
      };

        //Função iniciar API do Google Maps no Engenho Coradini
        function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: new google.maps.LatLng(-30.975773, -54.643425),
          zoom: 18,
          disableDoubleClickZoom: true
        });

        var overlay;
        USGSOverlay.prototype = new google.maps.OverlayView();

        // Planta
        var bounds = new google.maps.LatLngBounds(
          new google.maps.LatLng(-30.978666922597185, -54.64720201485761),
          new google.maps.LatLng(-30.97247385563734, -54.64060378076283));

            // Imagem da planta baixa da Filial
            var srcImage = 'img/' +
                'planta.png';

            // O USGS Overlay customizado contém um objeto dentro da USGS image,
            // o bounds dessa imagem, e a referência para o mapa.
            overlay = new USGSOverlay(bounds, srcImage, map);

            /** @constructor */
            function USGSOverlay(bounds, image, map) {

              // Inicializar todas as propriedades.
              this.bounds_ = bounds;
              this.image_ = image;
              this.map_ = map;

              // Define uma propriedade para segurar a imagem na div.
              // Cria essa div pronta para receber na variável onAdd()
              this.div_ = null;

              // Chamamos a função principal setMap para aplicar essa Overlay.
              this.setMap(map);
            };

            /**
             * onAdd é chamado quando os pane's do mapa estão prontos e o overlay foi
             * carregado no mapa.
             */
            USGSOverlay.prototype.onAdd = function() {

              var div = document.createElement('div');
              div.style.borderStyle = 'none';
              div.style.borderWidth = '0px';
              div.style.position = 'absolute';

              // Cria o elemento img e anexa na div.
              var img = document.createElement('img');
              img.src = this.image_;
              img.style.width = '100%';
              img.style.height = '100%';
              img.style.position = 'absolute';
              div.appendChild(img);

              this.div_ = div;

              // Adiciona o elemento para o "overlayLayer" pane.
              var panes = this.getPanes();
              panes.overlayLayer.appendChild(div);
            };

            //Verificar se o navegador é internet explorer para desabilitar ferramenta de calculo
            CheckIE();
                function CheckIE()
                {
                var Browser;
                Browser = navigator.userAgent;
                if (Browser.indexOf("Trident") == -1)
                {
                  //Variavel para calculo de distancia
                  var measureTool = new MeasureTool(map, {
                    showSegmentLength: true,
                    unit: MeasureTool.UnitTypeId.METRIC
                  });
              }
              };

            USGSOverlay.prototype.draw = function() {

              // Usa-se sul-oeste e norte-leste
              // coordenadas de overlay para posicionar na posição e tamanho correto.
              // Requisitar a projeção do overlay.
              var overlayProjection = this.getProjection();

              // Requisitar a coordenada sul-oeste e o norte-leste do overlay
              // usando LatLngs e convertendo para coordenadas pixelares.
              // Usando as coordenadas para redimencionar a div.
              var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
              var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

              // redimencionar a div da imagem para posicionar nas dimensões indicadas.
              var div = this.div_;
              div.style.left = sw.x + 'px';
              div.style.top = ne.y + 'px';
              div.style.width = (ne.x - sw.x) + 'px';
              div.style.height = (sw.y - ne.y) + 'px';
            };

            // O metodo onRemove() irá ser chamada automaticamente do API se
            // setar o overlay do mapa para 'null'.
            USGSOverlay.prototype.onRemove = function() {
              this.div_.parentNode.removeChild(this.div_);
              this.div_ = null;
            };


            google.maps.event.addDomListener(window, 'load', initMap);

            // Planta
            var bounds2 = new google.maps.LatLngBounds(
              new google.maps.LatLng(-30.968439407164297, -54.67410671709331),
              new google.maps.LatLng(-30.96703360588649, -54.672603338960926));

                // Imagem da planta baixa da Matriz
                var srcImage2 = 'img/' +
                    'planta2.jpg';

                // O USGS Overlay customizado contém um objeto dentro da USGS image,
                // o bounds dessa imagem, e a referência para o mapa.
                overlay = new USGSOverlay(bounds2, srcImage2, map);

                /** @constructor */
                function USGSOverlay(bounds2, image, map) {

                  // Inicializar todas as propriedades.
                  this.bounds_ = bounds2;
                  this.image_ = image;
                  this.map_ = map;

                  // Define uma propriedade para segurar a imagem na div.
                  // Cria essa div pronta para receber na variável onAdd()
                  this.div_ = null;

                  // Chamamos a função principal setMap para aplicar essa Overlay.
                  this.setMap(map);
                };

                /**
                 * onAdd é chamado quando os pane's do mapa estão prontos e o overlay foi
                 * carregado no mapa.
                 */
                USGSOverlay.prototype.onAdd = function() {

                  var div = document.createElement('div');
                  div.style.borderStyle = 'none';
                  div.style.borderWidth = '0px';
                  div.style.position = 'absolute';

                  // Cria o elemento img e anexa na div.
                  var img = document.createElement('img');
                  img.src = this.image_;
                  img.style.width = '100%';
                  img.style.height = '100%';
                  img.style.position = 'absolute';
                  div.appendChild(img);

                  this.div_ = div;

                  // Adiciona o elemento para o "overlayLayer" pane.
                  var panes = this.getPanes();
                  panes.overlayLayer.appendChild(div);
                };

                USGSOverlay.prototype.draw = function() {

                  // Usa-se sul-oeste e norte-leste
                  // coordenadas de overlay para posicionar na posição e tamanho correto.
                  // Requisitar a projeção do overlay.
                  var overlayProjection = this.getProjection();

                  // Requisitar a coordenada sul-oeste e o norte-leste do overlay
                  // usando LatLngs e convertendo para coordenadas pixelares.
                  // Usando as coordenadas para redimencionar a div.
                  var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
                  var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

                  // redimencionar a div da imagem para posicionar nas dimensões indicadas.
                  var div = this.div_;
                  div.style.left = sw.x + 'px';
                  div.style.top = ne.y + 'px';
                  div.style.width = (ne.x - sw.x) + 'px';
                  div.style.height = (sw.y - ne.y) + 'px';
                };

                // O metodo onRemove() irá ser chamada automaticamente do API se
                // setar o overlay do mapa para 'null'.
                USGSOverlay.prototype.onRemove = function() {
                  this.div_.parentNode.removeChild(this.div_);
                  this.div_ = null;
                };


                google.maps.event.addDomListener(window, 'load', initMap);


        //Variaveis de alternancia de foco matriz/filial
        var centerControlDiv = document.createElement('div');
        var centerControl = new CenterControl(centerControlDiv, map);

        var centerControlDiv2 = document.createElement('div2');
        var centerControl2 = new CenterControl2(centerControlDiv2, map);

        centerControlDiv.index = 1;
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);

        centerControlDiv2.index = 1;
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv2);

        // Variavel para abrir a caixa de informação contendo a latitude e longitude
        var infoWindow = new google.maps.InfoWindow;

        // Variavel de localização e marcação de pontos em tempo real no mapa temporariamente
        var geocoder = new google.maps.Geocoder;

        // Função criar marcador temporário ao clicar no botão 'Procurar' com as coordenadas preenchidas

        document.getElementById('busca').addEventListener('click', function() {
                  geocodeLatLng(geocoder, map, infoWindow);
                });

        //Função procurar e marcar localizações no mapa usando o campo latitude e longitude
        function geocodeLatLng(geocoder, map, infowindow) {
       var input1 = document.getElementById('latMap').value;
       var input2 = document.getElementById('lngMap').value;
       var latlng = {lat: parseFloat(input1), lng: parseFloat(input2)};
       geocoder.geocode({'location': latlng}, function(results, status) {
         if (status === 'OK') {
           if (results[1]) {
             map.setZoom(19);
             map.setCenter(latlng);
       var marker = new google.maps.Marker({
             position: latlng,
             map: map,
             icon: 'img/green-dot.png'
           });

           infowindow.setContent('Marcador temporário');
           infowindow.open(map, marker);

         } else {
           window.alert('Nenhum resultado foi encontrado');
         }
       } else {
         window.alert('Geolocalização falhou devido a: ' + status);
       }
         marker.addListener("click", function(){
         marker.setMap(null);
         window.open('equipamentos.php?id=1', '_blank', "height=800, width=1000, scrollbars=yes").focus();
       });
     });
    }

    var timeoutId = 0;

    document.getElementById('converter').addEventListener('click', function() {
        var lat = document.getElementById("latMap").value;
        var lng = document.getElementById("lngMap").value;
            ddToDms(lat, lng);
            });

        // conversion string in DD to DMS.
        function ddToDms(lat, lng) {

          var latResult, lngResult, dmsResult;

           lat = parseFloat(lat);
           lng = parseFloat(lng);

           latResult = (lat >= 0)? 'N' : 'S';

           // Call to getDms(lat) function for the coordinates of Latitude in DMS.
           // The result is stored in latResult variable.
           latResult += getDms(lat);

           lngResult = (lng >= 0)? 'L' : 'O';

           // Call to getDms(lng) function for the coordinates of Longitude in DMS.
           // The result is stored in lngResult variable.
           lngResult += getDms(lng);

           document.getElementById("latMap").value = latResult;
           document.getElementById("lngMap").value = lngResult;

        }

  function getDms(val) {

  var valDeg, valMin, valSec, result;

  val = Math.abs(val);

  valDeg = Math.floor(val);
  result = valDeg + "º";

  valMin = Math.floor((val - valDeg) * 60);
  result += valMin + "'";

  valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000) / 1000;
  result += valSec + '"';

  return result;
}

        // Função de pegar as coordenadas com o clique no mapa
        google.maps.event.addListener(map, 'click', function(event) {
                            document.getElementById('latMap').value = event.latLng.lat();
                            document.getElementById('lngMap').value = event.latLng.lng();
                        });


                    function mapDivClicked (event) {
                        var target = document.getElementById('map'),
                            posx = event.pageX - target.offsetLeft,
                            posy = event.pageY - target.offsetTop,
                            bounds = map.getBounds(),
                            neLatlng = bounds.getNorthEast(),
                            swLatlng = bounds.getSouthWest(),
                            startLat = neLatlng.latitude(),
                            endLng = neLatlng.longitude(),
                            endLat = swLatlng.latitude(),
                            startLng = swLatlng.longitude();

                        document.getElementById('posX').value = posx;
                        document.getElementById('posY').value = posy;
                        document.getElementById('latitude').value = startLat + ((posy/350) * (endLat - startLat));
                        document.getElementById('longitude').value = startLng + ((posx/500) * (endLng - startLng));
                    };


          // Função para pegar e executar formulário XML para pegar ID no banco
          downloadUrl('resultado.php', function(data) {
            var xml = data.responseXML;
            var markers = xml.documentElement.getElementsByTagName('marker');
            Array.prototype.forEach.call(markers, function(markerElem) {
              var name = markerElem.getAttribute('name');
              var link = markerElem.getAttribute('link');
              var descricao = markerElem.getAttribute('descricao');
              var point = new google.maps.LatLng(
                  parseFloat(markerElem.getAttribute('lat')),
                  parseFloat(markerElem.getAttribute('lng')));

              //Função abrir descrição do banco de dados na caixa de informações dos marcadores fixos
              var infowincontent = document.createElement('div');
              var strong = document.createElement('strong');
              strong.textContent = name
              infowincontent.appendChild(strong);
              infowincontent.appendChild(document.createElement('br'));
              var text = document.createElement('text');
              text.textContent = descricao
              infowincontent.appendChild(text);
              var icon = customLabel[descricao] || {};

              //Função posicionar marcadores fixos baseados nos dados no BD
              var marker = new google.maps.Marker({
                map: map,
                position: point,
                label: icon.label,
                optimized: false,
                zIndex: 1
              });

              // Função de abrir infobox + link para listagem de equipamento dentro do marcador fixado do BD
              marker.addListener('mouseover', function() {
                window.name = "principal";
                infoWindow.setContent(infowincontent);
                infoWindow.open(map, marker);
              });
              marker.addListener('click', function(){
                // Delay de 2 segundos para abrir a janela contendo os equipamentos baseados na ID ligadas na foreign key do BD
                setTimeout(function(){
                window.open(link, '_blank', "height=800, width=1000, scrollbars=yes").focus();
              }, 700);
              });
            });
          });
        }

      function downloadUrl(url, callback) {
        var request = window.ActiveXObject ?
            new ActiveXObject('Microsoft.XMLHTTP') :
            new XMLHttpRequest;

        request.onreadystatechange = function() {
          if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request, request.status);
          }
        };

        request.open('GET', url, true);
        request.send(null);
      }


      function doNothing() {}

    </script>

In the PHP part of the project, there is no function or anything that calls the function. They are all called from javascript.

1 answer

2


Your problem is in the code that retrieves the form values. Which is this one:

var lat = document.getElementById("latMap").value;
var lng = document.getElementById("lngMap").value;

When the above code is executed, the form still has no values. Just add them inside the Event Listener

document.getElementById('converter').addEventListener('click', function() {
    var lat = document.getElementById("latMap").value;
    var lng = document.getElementById("lngMap").value;

    ddToDms(lat, lng);
});

// conversion string in DD to DMS.
function ddToDms(lat, lng) {
    var latResult, lngResult, dmsResult;

    lat = parseFloat(lat);
    lng = parseFloat(lng);

    latResult = (lat >= 0)? 'N' : 'S';
    // Call to getDms(lat) function for the coordinates of Latitude in DMS.
    // The result is stored in latResult variable.

    latResult += getDms(lat);
    lngResult = (lng >= 0)? 'L' : 'O';

    // Call to getDms(lng) function for the coordinates of Longitude in DMS.
    // The result is stored in lngResult variable.
    lngResult += getDms(lng);

    document.getElementById("latMap").value = latResult;
    document.getElementById("lngMap").value = lngResult;
}

function getDms(val) {
    var valDeg, valMin, valSec, result;

    val = Math.abs(val);

    valDeg = Math.floor(val);
    result = valDeg + "º";

    valMin = Math.floor((val - valDeg) * 60);
    result += valMin + "'";

    valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000) / 1000;
    result += valSec + '"';

    return result;
}
<div id="row" class="row">
    <div class="col-md-12">
        <label for="latMap">Latitude:</label>
        <input id="latMap" class="form-control"/>
    </div>

    <div class="col-md-12">
        <br>
          <label for="lngMap">Longitude:</label>
          <input id="lngMap" class="form-control" />
    </div>
</div>

<button id="converter" class="btn btn-primary">
    <i class="fas fa-redo-alt"></i> GMS
</button>

Thus, values will be recovered correctly.

Also, I performed some HTML fixes and removed the H1 to make it more readable here in the OS.

Update

Execution:

inserir a descrição da imagem aqui

Output:

inserir a descrição da imagem aqui

Is just without the CSS, but proves that the code works.

  • Thanks for the reply, but unfortunately it has no effect, it is still showing "Nan" when I click on the GMS button.

  • @brnTwp Did you execute the code here in the OS? It is working correctly. I will add an image. Update your code so that we can validate.

  • Yes, I tested it here and then I tested it in my project, here it works, there it remains the same. I do not know what is happening for him to still assign "Nan" to the values.

  • If it works here and there it does not, there is something that is different. Check that nothing was missing in the code you posted. Validate if there are no repeated id’s, etc...

  • I took a look at my code and it looks like my button is running twice! Even clicking only once on it, it performs the function 2 times, which practically explains why the value "Nan", because in the first of the 2 times that the function is executed, it does correct, but as it is duplicating, it takes the transformed value and tries to do with the value already ready, as it is already ready, it ends up getting lost in the calculation of getDMS resulting in Nan.

  • Only, in my code, I only identified 1 id corresponding to the eventlistener, nothing else! There’s nothing duplicated about the click function, I don’t understand why it’s duplicating. There’s a way to limit or if you’ve seen this problem?

  • @brnTwp posts the full code

  • Code in question.

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.