0:00 0 0
Mapas con Bing

Mapas con Bing

  DrUalcman |  febrero 142019

Estimado lector. Como sabrás Google ha cambiado mucho, ya no es tan altruista, ahora quiere rentabilizar al máximo todos sus productos, entre ellos el Google Maps. Ya no es tan fácil utilizar esta tecnología sin que tengas que pagar por ello. No obstante, no deja de ser un gran servicio. Pero aun así hay muchas otras opciones en la GRAN RED DE INTERNET que podemos utilizar, y sobre uno de ellos es del que os quiero hablar hoy.

Microsoft, al contrario que Google, si que cada día parece volverse más altruista. Ha comprendido que compartiendo sus códigos, y que abriendo su tecnología, cada día más programadores optan por sus productos a la hora de elegir una tecnología, ya sea para programar o para utilizar alguno de sus servicios. Aunque Microsoft también tiene su versión de pago, Bing Maps es una gran alternativa a Google Maps, y con la experiencia que he tenido, hasta me ha parecido mucho más sencillo de implementar. Pero esto también puede haber sido por haber pasado ya la experiencia de haber realizado una integración con Google Maps, y claro, ahora asimilar los conceptos y aplicarlos ha sido mucho más fácil.

Me voy a centrar sólo en la versión para la web, pero no descarto dentro de poco hacer otro post de cómo integrarlo dentro de una aplicación de escritorio, pero, en mi caso, pocas veces he necesitado implementar mapas en software de escritorio, y por eso aún no me he puesto con ello.

Puedes acceder al repositorio en Download MapsBing Download MapsBing

Primeros pasos

Como es habitual, lo primero que debemos hacer es solicitar una APIKEY para poder trabajar. Yo recomiendo que tengas una dirección de correo electrónico de las de Microsoft ya sea @hotmail, @msn, o cualquiera de sus dominios. Esto te simplificará el proceso de registro gracias a su sistema de inicio de sesión multiple.

 Registro en Bing Maps Portal 


Registrarse es muy rápido y fácil. Sobre todo si tienes una cuenta de Microsoft, como ya he mencionado antes.

Registro

Cuenta

Una vez nos hayamos registrado accederemos a nuestra cuenta, desde este lugar administraremos nuestras ApiKey.

Debes de tener en cuenta que Microsoft diferencia bastante el uso que se da a cada Key, por lo que debes de tener cuidado a la hora de crear una Key que sea para la plataforma en donde la vas a utilizar.

En nuestro caso, será una ApiKey para web , por lo que deberemos de seleccionar Public website. Una observación, este portal está solo disponible en Inglés, por lo que espero que te sepas manejar un poco con este idioma.

Para crear nuesta ApiKey nos desplazaremos por el menú de My account y seleccionaremos el submenú My Keys.

Tras esperar unos pocos segundos nos mostrará una lista con todas las Keys que hayamos generado, que evidentemente, estará vacío si es la primera vez que nos hemos registrado.

Una vez en se haya cargado la página, pulsaremos en Click here to create a new key. Se nos abrirá una ventana para rellenar los datos básicos de nuestra App que va a utilizar esta ApiKey.

Application name: Utiliza el nombre de tu proyecto o algo descriptivo para que sepas para quien es esta Key.

Application URL: No es obligatorio, pero si se trata de una web, no esta de más incluir aquí la página que usa esta Key, así nos será fácil recordar dónde la estamos usando.

Key type: Este campo, obligatorio, es un poco "tonto" ya que en la versión gratuita solo admite un tipo Basic, por lo que lo dejamos como está.

Application type: Y aquí es dónde no podemos equivocarnos, si no la Key no nos dejará ser utilizada, debemos seleccionar Public website, ya que la vemos a utilizar desde una web, en este caso.

ApiKeys

Finalmente para poder conocer la ApiKey para nuestra aplicación, sólo tenemos que pulsar donde pone Show key y copiarla para utilizarla luego.

Manos a la obra

Primero incluiremos en el HEAD de la página la llamada a la librería de Bing Maps.

< script type="text/javascript" src=http://www.bing.com/api/maps/mapcontrol?key=[YOUR_BING_MAPS_KEY] async defer >< /script >

Luego le damos un lugar en la página donde alojar el mapa

< div id="myMap" style="position:relative;width:600px;height:400px;" >< /div >

Y por último incluimos el script para que nos cargue el mapa.

    < script type="text/javascript" >
    function GetMap()
    {
        var map = new Microsoft.Maps.Map("#myMap");
        //Add your post map load code here.
    }
   GetMap();
    < /script >

Esto sería lo más básico para hacer que se muestre directamente el mapa en nuestra web. Aqui te muestro como sería la página básica para mostrar el mapa.

< !DOCTYPE html >
< html >
< head >
    < title >Bing Maps< /title >
    < meta charset="utf-8" / >
    < !- - Reference to the Bing Maps SDK - - >
    < script type="text/javascript"
            src="http://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[YOUR_BING_MAPS_KEY]"
            async defer>< /script >
    < script type="text/javascript" >
    function GetMap()
    {
        var map = new Microsoft.Maps.Map("#myMap");
        //Add your post map load code here.
    }
    < /script >
< /head >
< body >
    < div id="myMap" style="position:relative;width:600px;height:400px;" >< /div >
< /body >
< /html >

Primeros pasos web oficial

Lo importante es simplificar el trabajo

Como a mi no me gusta estar repitiendo siempre lo mismo en todas partes, he creado un script para simplificar un poco esta trabajo. Pero al finalizar el script entero parece complicado, es por ello que intentaré comentar el uso de las principales funciones como Mostrar Mapa, Sugerencias de Direcciones y Trazar Rutas. Al final incluiré el código para que lo disfrutéis.

Configuración

Voy primero a explicar como es la configuración del script. El principal motivo de crear este escrip fue simplificar y no tener que estar siempre escribiendo las mismas lineas de código en cada página, pero lamentablemente, lo que es la configuración, y obviamente, en enlace al script es algo que tendremos que hacer si o si en cada página dónde lo queramos usar. La ventaja es que con sólo un enlace y una declaración ya dispondremos de todas las herramientas a nuestro alcance.

              {
                    credentials: '',                        //credenciales de la API de Bing Maps
                    branch: 'release',                      //release or experimental
                    setLang: 'ES',                          //idioma a mostrar, pero si estas identificado con una cuenta de Microsoft cogerá tu idioma de la cuenta
                    setMkt: 'es-ES',                        //cultura a utilizar, para mostrar Km o millas, por ejemplo
                    errorBox: '', //Id del contenedor donde mostrar los errores al usuario, por ahora solo se utiliza en el modulo de sugerencias
                    country: null, //Si se especifica un código de País (Formato ISO= se delimitará la busqueda a dicho país
                    detectLocation: false, //Si esta en true se intentara detectar la ubicación del usuario
                    loadScript: true, //Esta es la clave de mi script, si esta en true automaticamente incluira en el HEAD el script de Bing Maps, si lo dejas como false deberás poner tu la declaración en el HEAD de la página
                    delay: 1500, //Este es el retardo para cargar la función, siempre será necesario un mínimo de 750 mili segundos a 1500 ya que el script de Bing Maps tiene que ser cargado antes de que este script commience a hacer llamadas
                    ShowMap: {                              //modulo para mostrar mapas
                        Container: '', //Id del contenedor para el mapa
                        Options: { //Opciones de configuracion del mapa
                            zoom: 16                        //Por defecto solo utilizo el zoom a 16, los valores son de 1 a 20
                        }
                    },
                    SuggestBox: {                           //modulo para sugerir direciones
                        searchText: '', //Id del contenedor para escribir la busqueda, normalmente sera un textbox
                        searchBox: '', //Id del contenedor para mostrar los resultados, suele ser un DIV debajo del textbox, pero realmente lo puede situar donde mas te convenga en la página
                        addressDestination: { //Configuracion donde se va a mostrar la dirección obtenida. Definicion de los Id donde mostrar cada dato
                            Street: '',
                            City: '',
                            State: '',
                            Country: '',
                            CountryISO: '',
                            PostCode: '',
                            FullAddress: ''
                        },
                        maxResults: 10, //Número máximo de resultados a mostrar. Maximo creo que es 20
                        hideAfterSelect: false, //Si es true ocultara el contador definido en searchText
                        autoFillSuggestResult: true, //Si es true rellenarán los contenedores definidos en addressDestination
                        fixedHeigh: false, //Este depende de si hideAfterSelect es true. Y si lo ponemos a true ocultará el contenedor de searchText
                        CallBackAfterSuggest: null, //Función a realizar tras el seleccionar la sugerencia
                        situarMapa: false //Si es true mostrara el mapa de con el punto de la dirección seleccionada. Depende de si hemos cargado el mapa o no.
                    },
                    DirectionsMap: { //Configuración del módido de trazado
                        directionsPanel: '', //Id del contenedor para el panel de busqueda
                        directionsItinerary: '' //Id del contenedor para el itinerario del trazado
                    }
                };
            }

Aclaraciones

El módulo de sugerencias, tras seleccionar una sugerencia devuelve un evento llamado SuggestClick. Además éste módulo no tiene porque ser cargado con el mapa, se puede cargar independiente, por lo que no mostraría mapa, solo sugerencias.

El módulo de trazado, a diferencia de Google Maps, tiene la ventaja de que en el directionsPanel nos crea el formulario para la búsqueda y trazado de direcciones, por lo que nos ahorramos tener que dibujar en nuestra página dichos elementos y podemos utilizar lo que Bing Maps nos proporciona.

Cargar el script

Puedes descargar el script completo aquí o, si deseas modificar algo para adaptarlo mejor a tu web, puedes copiar el código que te dejo al final del documento. Aquí os dejo la ruta desde mi servidor, es un servidor seguro. Por si no queréis ni siquiera descargar el script. Lo podéis utilizar directamente desde mi servidor.

< script src="https://community-mall.com/js/mapsBing.js" >< /script >

Luego delcaramos el script de la siguiente manera:

        var mapsB = new MapsBing({
            credentials: '[YOUR_BING_MAPS_KEY]',
            ShowMap: {
                Container: 'myMap',
                Options: {
                    zoom: 16                        //1-20
                }
            },
            delay: 1500
        });

El script si no le envías tu ApiKey directamente te da error, así evitamos tener que hacer llamadas al script de Bing Maps y no nos afectará al rendimiento de la página. Como puedes ver es una forma bastante sencilla de hacer la declaración.

Version 1.1.6: Ya no es necesario el envío de la ApiKey. Pero entonces tendrás que enviarla inicializando el módulo que desees utilizar con la ApiKey.

Propiedades

  • VERSION: Devuelve la versión del script
  • LOCATION: Devuelve la última localización encontrada
  • MY_LOCATION: Devuelve mi localización, si se ha podio obtener
  • CONFIG: Devuelve la configuración actual del script

Métodos

  • GeoCoder: Busca las coordenadas de latitud y longitud de una dirección. Esta función es una promesa
  • GetAddressFromPoint: Geolocalización inversa, es decir, nos devolverá una dirección de una latitud y longitud dadas. Esta función es una promesa
  • MuestraMapa: Nos posicionará el punto de las coordenadas enviadas
  • GetDirections: Muestra el trazado de la tuda desde el punto A al punto B
  • GetPosition: Devuelve mi posición actual. Esta función es una promesa
  • LoadSuggest: Cargar el módulo de sugerencias con la configuración enviada, si no se envía configuración utilizará la por defecto al declarar el script.

Mostrar un mapa

Para  mostrar el mapa tenemos dos formas de hacerlo. Si hemos cargado el módulo de sugerencias, entonces sólo tenemos que habilitar en la configuración que nos sitúe el mapa y listo. Una vez que seleccionemos la sugerencia nos mostrará directamente el punto en el mapa. Ésta sería la forma más sencilla y, como norma general, la más utilizada.

Otra forma es llamar a la función muestraMapa, pero para ello primero necesitamos saber las coordenadas de la localización. Por lo que si no la tenemos, deberíamos primero ejecutar la función GeoCoder para obtener la localización y cuando la encuentra entonces mostrar el mapa. Teniendo en cuenta que GeoCoder devuelve una promesa, podemos poner dentro de la devolución de la promesa la función muestraMapa recogiendo el valor enviado por la misma.

let query = "Madrid";
mapsB.GeoCoder(query).then(function (localizacion) {
                mapsB.MuestraMapa(localizacion);
            }):

Este sería un ejemplo para mostrar el mapa si no tenemos la localización exacta.

Cargar las sugerencias

Para cargar las sugerencias, al declarar el objeto podemos indicarle dónde queremos que se carguen, pero si por ejemplo, tenemos varios textbox dónde queremos que se carguen las sugerencias, es necesario indicar al script dónde en cada momento. Ésta es una de las funciones que con mi script se mejora y se hace más fácil, ya que con la documentación de Bing Maps no queda claro como poder asignar las sugerencias en más de un texto box. 

Para ello llamaremos a la funcion LoadSuggest y le enviaremos la configuración con los datos del lugar donde queremos que se muestren las sugerencias.

< label for="origen" >Origen< /label >
< input type="text" name="origen" onclick="SetSuggest('origen','bing')" id="origen" placeholder="calle, ciudad, estado..." / >
< div id="bing" >< /div >
< script >
        function SetSuggest(box, suggest) {
            let config = {
credentials: '[YOUR_BING_MAPS_KEY]', //si no la has enviado al declarar el objeto
                SuggestBox: {
                    searchText: box,
                    searchBox: suggest,
                    autoFillSuggestResult: false,
                    maxResults: '10',
                    situarMapa: false
                }
            };
            mapsB.LoadSuggest(config);
        }
< /script >

Esto sería un ejemplo de la función a llamar al hacer click, en mi ejemplo, en el textbox para cargar las sugerencias. Evidentemente si tuviéramos mas de un textbox deberíamos enviar siempre el ID del texto box que estamos haciendo click. La función también la puedes cambiar y en lugar de enviar un texto plano con el ID puedes hacerlo de otras maneras, pero eso ya queda a tu criterio, esto es sólo una muestra orientativa.

Trazado de direcciones

Finalmente para trazar una dirección utilizaremos la función GetDirections a la que le pasamos directamente el texto de la dirección origen, punto A, a la dirección destino, punto B. Por desgracia mi script sólo contempla esas dos posibilidades, pero si estamos utilizando el panel que nos crea Bings Maps tenemos la posibilidad de agregar más puntos, he incluso de cambiar la forma en la que queremos ir, caminando, en coche...

Mi script solo contempla la posibilidad de pedir un trazado del punto  A al punto B ya que está pensado para, por ejemplo, una tienda online, o un blog con un evento, para decir como llegar desde donde está el usuario a donde estoy yo. Un ejemplo facil sería este.

let origen = "Madrid";
let destino = "Barcelona";
mapsB.GetDirections(origen, destino);

El evento SuggestClick

Para finalizar explicar un poco por encima el evento que devuelve el script. Una vez se pulsa una sugerencia el script siempre devolverá un evento que podemos capturar con los datos de la sugerencia. Un ejemplo de como capturar este evento es.

    document.addEventListener('SuggestClick', function (e) {
        console.log(e.detail.address);          //contiene la direcion seleccionada
    }, false);

El Script al completo

Aquí os dejo el script al completo para si lo queréis modificar. Si encontráis como mejorarlo, por favor, comparte conmigo y así podré actualizar este post y que todos podamos disfrutar de las mejoras introducidas. Pero como ya he comentado más arriba tenéis el repositorio en este enlace.

/**
* @description Libreria para utilizar Bing Maps
* @author DrUalcman 2019 https://aprende-a-programar.com/b/Mapas-con-Bing/
* @param {any} configuracion opciones de configuracion
* @license GNU General Public License version 3.0 (GPLv3)
*/
function MapsBing(configuracion) {
/**
* GLOBALS VARIABLES
*/
let VERSION = '1.1.6';
let LOCATION = { Lat: 0, Lng: 0, Address: "" };
let MY_LOCATION = { Lat: 0, Lng: 0, Address: "" };
let CONFIG;

/**
* Management maps
*/
let map = null;
let searchManager = null;
let directionsManager = null;

try {
if (configuracion === undefined || configuracion === '' || configuracion === null) {
CONFIG = mapsOptions(); /* Default Config */
} else {
CONFIG = _mergeOptions(mapsOptions(), configuracion);
}
if (CONFIG.loadScript) loadScript();
else setTimeout(loadMapScenario, CONFIG.delay);
} catch (e) {
console.error(e);
}

/**********************
* Public Functions
***********************/

/** Conover la version */
MapsBing.prototype.Version = VERSION;
/** Obtener la configuracion */
MapsBing.prototype.Config = CONFIG;
/** Obtener la localizacion */
MapsBing.prototype.Location = LOCATION;
/** Obtener la localizacion */
MapsBing.prototype.MyLocation = MY_LOCATION;
/**
* @description Buscar la geolocalizacion de una direccion.
* @param {any} query direccion a buscar
* @returns {Promise} devuelve una promesa con la localizacion y situa directamente el mapa en el resultado
*/
MapsBing.prototype.GeoCoder = function (query) {
return new Promise(function (resolver, rechazar) {
geoCoder(query)
.then(function (location) {
resolver(location);
},
function (miError) {
rechazar(miError);
});
});
};
/**
* @description Buscar la geolocalizacion de una direccion.
* @param {any} location direccion a buscar
* @returns {Promise} devuelve una promesa con la localizacion y situa directamente el mapa en el resultado
*/
MapsBing.prototype.GetAddressFromPoint = function () {
return new Promise(function (resolver, rechazar) {
getAddressFromPoint()
.then(function (location) {
resolver(location);
},
function (miError) {
rechazar(miError);
});
});
};
/**
* Mostrar el mapa de una localizacoin
* @param {JSON} location JSON con la latitud y longitud como { Lat: 0, Lng: 0 }
* @param {JSON} point JSON la descripcion del punto { title: '', subTitle: '', text: '' }
* @param {JSON} info JSON con el texto de visualizacioin en el blobo { title: '', description: '[acepta HTML]' }
* @param {string} html html para personalizar el blobo
* @param {array} acciones Array con las acciones a mostrar [{ label: 'Handler1', eventHandler: function () { alert('Handler1'); } }]
* @param {number} zoom nivel de zoom 1 - 20
*/
MapsBing.prototype.MuestraMapa = function (location, point, info, html, acciones, zoom) {
if (map) {
if (zoom === undefined || zoom === '' || zoom === null) zoom = 17;
if (location === undefined || location === '' || location === null) location = MY_LOCATION;
let lat = location.Lat;
let lng = location.Lng;
if (point === undefined || point === '' || point === null) point = {
title: 'Latitud: ' + lat,
subTitle: 'Lomgitud: ' + lng,
text: '*'
};
if (info === undefined || info === '' || info === null) info = {
title: JSON.stringify(location),
description: 'Latitud: ' + lat + '
Lomgitud: ' + lng,
showPointer: true,
showCloseButton: true,
visible: false,
actions: [],
htmlContent: ''
};
if (html !== undefined || html !== '' || html !== null) {
let infoHTML = {
htmlContent: html === undefined ? '' : html
};
info = _mergeOptions(info, infoHTML);
}
if (acciones !== undefined || acciones !== '' || acciones !== null) {
let infoAcciones = {
actions: acciones === undefined ? [] : acciones
};
info = _mergeOptions(info, infoAcciones);
}
let config = {
mapTypeId: Microsoft.Maps.MapTypeId.road,
center: new Microsoft.Maps.Location(lat, lng),
zoom: zoom
};
config = _mergeOptions(mapsOptions().ShowMap.Options, config); /* Default Config */
map.setView(config);

let center = map.getCenter();
let infobox = new Microsoft.Maps.Infobox(center, info);
//Assign the infobox to a map instance.
infobox.setMap(map);
//Create custom Pushpin
let pin = new Microsoft.Maps.Pushpin(center, point);
//Add a click event handler to the pushpin.
Microsoft.Maps.Events.addHandler(pin, 'click', function (e) {
//Set the infobox options with the metadata of the pushpin.
if (infobox.getVisible())
infobox.setOptions({
visible: false
});
else
infobox.setOptions({
visible: true
});
});
//Add the pushpin to the map
map.entities.push(pin);
}
else console.error('No se ha inicializado el mapa');
};
/**
* Mostrar las direcciones
* @param {JSON} origen JSON con la nueva conviguracion {address: 'mapa', location: {lat: 0, lng: 0}}
* @param {JSON} destino JSON con la nueva conviguracion {address:'mapa', location: {lat: 0, lng: 0}}
*/
MapsBing.prototype.GetDirections = function (origen, destino) {
if (directionsManager) {
try {
//Create waypoints to route between.
let origin = new Microsoft.Maps.Directions.Waypoint({ address: origen });
directionsManager.addWaypoint(origin);
if (destino === undefined || destino === '' || destino === null) destino = MY_LOCATION.Address;
let destination = new Microsoft.Maps.Directions.Waypoint({ address: destino });
directionsManager.addWaypoint(destination);
//Calculate directions.
directionsManager.calculateDirections();
} catch (e) {
console.error('Error al cargar Microsoft.Maps.Directions');
console.error(e);
}
}
else console.error('No se ha cargado el modulo de direcciones');
};
/**
* Recoger mi posicion actual
* @returns {Promise} devuelve una promesa con la localizacion
*/
MapsBing.prototype.GetPosition = function () {
return new Promise(function (resolver, rechazar) {
getPosition()
.then(function (location) {
resolver(location);
},
function (miError) {
rechazar(miError);
});
});
};

/**
* @description Buscar la geolocalizacion de una direccion.
* @param {any} opciones direccion a buscar
*/
MapsBing.prototype.LoadSuggest = function (opciones) {
loadSuggest(opciones);
};

/**********************
* Private Functions
***********************/

/**
* @description Cambiar las opciones de configuracion
* @param {any} opciones JSON con las opciones de configuracion
*/
function setConfig(opciones) {
if (opciones !== undefined && opciones !== '' && opciones !== null) {
CONFIG = _mergeOptions(CONFIG, opciones);
}
}

/** Cargar los scripts de bing */
function loadScript() {
//https://es.stackoverflow.com/questions/1366/c%C3%B3mo-incluir-un-archivo-javascript-a-otro-archivo-javascript-sin-utilizar-jquer
let head = document.getElementsByTagName('head')[0];
let script = document.createElement('script');
script.type = 'text/javascript';
if (CONFIG.credentials.length > 1) script.src = 'https://www.bing.com/api/maps/mapcontrol?branch=' + CONFIG.branch + '&setLang=' + CONFIG.setLang + '&setMkt=' + CONFIG.setMkt + '&key=' + CONFIG.credentials;
else script.src = 'https://www.bing.com/api/maps/mapcontrol?branch=' + CONFIG.branch + '&setLang=' + CONFIG.setLang + '&setMkt=' + CONFIG.setMkt;
script.onload = setTimeout(loadMapScenario, CONFIG.delay);
head.appendChild(script);
}

/**
* @description Recargar el escenario con las nuevas opciones enviadas. Necesario si se cambian las opciones de configuracion
* @param {any} opciones Opcional, JSON con las opciones de configuracion
*/
function loadMapScenario(opciones) {
//if (opciones === undefined || opciones === '' || opciones === null) {
// CONFIG = mapsOptions(); /* Default Config */
//} else {
// CONFIG = _mergeOptions(mapsOptions(), opciones);
//}
if (opciones !== undefined || opciones !== '' || opciones !== null) {
setConfig(opciones);
}
loadMapa(opciones);
loadSuggest(opciones);
loadSearch();
loadDirections();
if (map) {
getPosition().then(function (location) {
if (map) {
let lat = location.Lat;
let lng = location.Lng;
let point = {
title: location.Address,
subTitle: 'Lat, Lng: ' + lat + ', ' + lng,
text: '*'
};
let info = {
title: location.Address,
description: 'Latitud: ' + lat + '
Lomgitud: ' + lng,
showPointer: true,
showCloseButton: true,
visible: false,
actions: [],
htmlContent: ''
};
let config = {
mapTypeId: Microsoft.Maps.MapTypeId.road,
center: new Microsoft.Maps.Location(lat, lng),
zoom: 19
};
map.setView(config);

let center = map.getCenter();
let infobox = new Microsoft.Maps.Infobox(center, info);
//Assign the infobox to a map instance.
infobox.setMap(map);
//Create custom Pushpin
let pin = new Microsoft.Maps.Pushpin(center, point);
//Add a click event handler to the pushpin.
Microsoft.Maps.Events.addHandler(pin, 'click', function (e) {
//Set the infobox options with the metadata of the pushpin.
if (infobox.getVisible())
infobox.setOptions({
visible: false
});
else
infobox.setOptions({
visible: true
});
});
//Add the pushpin to the map
map.entities.push(pin);
}
else console.error('No se ha inicializado el mapa');
});
}
}

/**
* @description Recargar el mapa con las nuevas opciones enviadas
* @param {any} opciones Opcional, JSON con las opciones de configuracion
*/
function loadMapa(opciones) {
if (opciones !== undefined || opciones !== '' || opciones !== null) {
setConfig(opciones);
}

if (CONFIG.ShowMap.Container !== '' && CONFIG.ShowMap.Container !== null) {
try {
let config = {
mapTypeId: Microsoft.Maps.MapTypeId.road,
credentials: CONFIG.credentials
};
if (opciones === undefined || opciones === '' || opciones === null) {
config = _mergeOptions(mapsOptions().ShowMap.Options, config); /* Default Config */
} else {
config = _mergeOptions(mapsOptions().ShowMap.Options, config); /* Default Config */
config = _mergeOptions(config, opciones);
}
map = new Microsoft.Maps.Map('#' + CONFIG.ShowMap.Container, config);
} catch (e) {
console.error('Error al cargar Microsoft.Maps.Map', e);
}
}
}

/**
* @description Cargar las sugerencias.
* @param {any} opciones Opcional, JSON con las opciones de configuracion
*/
function loadSuggest(opciones) {
if (opciones !== undefined || opciones !== '' || opciones !== null) {
setConfig(opciones);
}
if (CONFIG.credentials.length > 1) {
if (CONFIG.SuggestBox.searchText !== '' && CONFIG.SuggestBox.searchText !== null) {
try {
let options = {};
if (map) {
options = {
maxResults: CONFIG.SuggestBox.maxResults,
countryCode: CONFIG.country,
autoDetectLocation: CONFIG.detectLocation,
map: map,
useMapView: true
};
}
else {
options = {
maxResults: CONFIG.SuggestBox.maxResults,
countryCode: CONFIG.country,
autoDetectLocation: CONFIG.detectLocation,
useMapView: false
};
}
Microsoft.Maps.loadModule('Microsoft.Maps.AutoSuggest', {
credentials: CONFIG.credentials,
callback: function () {
var manager = new Microsoft.Maps.AutosuggestManager(options);
manager.attachAutosuggest('#' + CONFIG.SuggestBox.searchText, '#' + CONFIG.SuggestBox.searchBox, selectedSuggestion);
SendFoco(CONFIG.SuggestBox.searchText);
},
errorCallback: function (message) {
console.error(message);
}
});

} catch (e) {
console.error('Error al cargar Microsoft.Maps.AutoSuggest', e);
}
}
}
else throw 'API KEY for Bing Maps is requeried';
}

/**
* @description Cargar la busqueda de direccion y mostrar en el mapa
*/
function loadSearch() {
if (map) {
try {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
});
} catch (e) {
console.error('Error al cargar Microsoft.Maps.Search', e);
}
}
}

/**
* @description Cargar la busqueda de direccion y mostrar en el mapa
*/
function loadDirections() {
if (map) {
try {
//Load the directions module.
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function () {
//Create an instance of the directions manager.
directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
//configuracion
let config = {
directionsPanel: CONFIG.DirectionsMap.directionsPanel,
directionsItinerary: CONFIG.DirectionsMap.directionsItinerary
};
if (opciones !== opciones || opciones !== '' || opciones !== null) {
config = _mergeOptions(config, opciones);
}
//mostrar el panel de opciones de busqueda si hay contenedor
if (config.directionsPanel !== '' && config.directionsPanel !== null) {
//Specify the where to display the input panel
directionsManager.showInputPanel(config.directionsPanel);
}
//mostrar el panel de ruta si hay contenedor
if (config.directionsItinerary !== '' && config.directionsItinerary !== null) {
//Specify the element in which the itinerary will be rendered.
directionsManager.setRenderOptions({ itineraryContainer: '#' + config.directionsItinerary });
}
});
} catch (e) {
console.error('Error al cargar Microsoft.Maps.Directions', e);
}
}
}

/**
* Mostrar las sugerencias
* @param {any} suggestionResult resultados
*/
function selectedSuggestion(suggestionResult) {
try {
if (suggestionResult.address) {
if (CONFIG.SuggestBox.hideAfterSelect) {
let searchBox = document.getElementById(CONFIG.SuggestBox.searchText);
if (CONFIG.SuggestBox.fixedHeigh) searchBox.style.visibility = 'hidden';
else searchBox.style.display = 'none';
}
if (CONFIG.SuggestBox.CallBackAfterSuggest) ExternalCallBack(CONFIG.SuggestBox.CallBackAfterSuggest, suggestionResult);
else {
//crear un evento al hacer click en la lista de sugerencias
//compatibilidades https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
let eventSuggestClick = new CustomEvent('SuggestClick', { detail: suggestionResult });
eventSuggestClick.initEvent('SuggestClick', true, false);
eventSuggestClick.returnValue = true;
LOCATION.Lat = suggestionResult.location.latitude;
LOCATION.Lng = suggestionResult.location.longitude;
LOCATION.Address = suggestionResult.address.formattedAddress;
if (CONFIG.SuggestBox.autoFillSuggestResult) {
if (CONFIG.SuggestBox.addressDestination.Street !== '') setValue(CONFIG.SuggestBox.addressDestination.Street, suggestionResult.address.addressLine);
if (CONFIG.SuggestBox.addressDestination.City !== '') setValue(CONFIG.SuggestBox.addressDestination.City, suggestionResult.address.locality);
if (CONFIG.SuggestBox.addressDestination.State !== '') setValue(CONFIG.SuggestBox.addressDestination.State, suggestionResult.address.adminDistrict);
if (CONFIG.SuggestBox.addressDestination.Country !== '') setValue(CONFIG.SuggestBox.addressDestination.Country, suggestionResult.address.countryRegion);
if (CONFIG.SuggestBox.addressDestination.CountryISO !== '') setValue(CONFIG.SuggestBox.addressDestination.CountryISO, suggestionResult.address.countryRegionISO2);
if (CONFIG.SuggestBox.addressDestination.PostCode !== '') setValue(CONFIG.SuggestBox.addressDestination.PostCode, suggestionResult.address.postalCode);
if (CONFIG.SuggestBox.addressDestination.FullAddress !== '') setValue(CONFIG.SuggestBox.addressDestination.FullAddress, suggestionResult.address.formattedAddress);
document.dispatchEvent(eventSuggestClick);
}
else document.dispatchEvent(eventSuggestClick);
try {
if (CONFIG.SuggestBox.situarMapa) {
map.entities.clear();
map.setView({ bounds: suggestionResult.bestView });
let pushpin = new Microsoft.Maps.Pushpin(suggestionResult.location);
map.entities.push(pushpin);
}
} catch (e) {
console.error(e);
}
}
}
else {
let error = document.getElementById(CONFIG.errorBox);
error.innerText = 'Not found';
}
} catch (e) {
console.error(e);
}
}

/**
* @description Buscar la geolocalizacion de una direccion.
* @param {any} location direccion a buscar
* @returns {Promise} devuelve una promesa con la localizacion y situa directamente el mapa en el resultado
*/
function getAddressFromPoint(location) {
return new Promise(function (resolver, rechazar) {
if (map) {
if (searchManager) {
if (location === undefined || location === '' || location === null) location = MY_LOCATION;
let lat = location.Lat;
let lng = location.Lng;
let reverseGeocodeRequestOptions = {
location: new Microsoft.Maps.Location(lat, lng),
callback: function (answer, userData) {
LOCATION.Lat = answer.location.latitude;
LOCATION.Lng = answer.location.longitude;
LOCATION.Address = answer.address.formattedAddress;
map.setView({ bounds: answer.bestView });
map.entities.push(new Microsoft.Maps.Pushpin(reverseGeocodeRequestOptions.location));
resolver(LOCATION);
}
};
searchManager.reverseGeocode(reverseGeocodeRequestOptions);
}
else rechazar('No se ha cargado el modulo de Busqueda por direccion');
}
else rechazar('No se ha inicializado el mapa');
});
}

/**
* @description Buscar la geolocalizacion de una direccion.
* @param {any} query direccion a buscar
* @returns {Promise} devuelve una promesa con la localizacion y situa directamente el mapa en el resultado
*/
function geoCoder(query) {
return new Promise(function (resolver, rechazar) {
if (map) {
//If search manager is not defined, load the search module.
if (searchManager) {
let searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
let pin = new Microsoft.Maps.Pushpin(r.results[0].location);
map.entities.push(pin);
map.setView({ bounds: r.results[0].bestView });
LOCATION.Lat = r.results[0].location.latitude;
LOCATION.Lng = r.results[0].location.longitude;
LOCATION.Address = r.results[0].address.formattedAddress;
resolver(LOCATION);
}
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
rechazar("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
else rechazar('No se ha cargado el modulo de Busqueda por direccion');
}
else rechazar('No se ha inicializado el mapa');
});
}

/**
* Recoger mi posicion actual
* @returns {Promise} devuelve una promesa con la localizacion
*/
function getPosition() {
return new Promise(function (resolver, rechazar) {
if (!navigator.geolocation) {
rechazar("Geolocation is not supported by your browser");
}
else {
navigator.geolocation.getCurrentPosition(function (position) {
MY_LOCATION.Lat = position.coords.latitude;
MY_LOCATION.Lng = position.coords.longitude;
getAddressFromPoint(MY_LOCATION)
.then(function () {
MY_LOCATION.Address = LOCATION.Address;
MY_LOCATION.Lat = LOCATION.Lat;
MY_LOCATION.Lng = LOCATION.Lng;
resolver(MY_LOCATION);
},
function (miError) {
rechazar("Unable to retrieve your location. " + miError);
});
}, function () {
MY_LOCATION.Lat = 15.2440035;
MY_LOCATION.Lng = 120.56041769999999;
getAddressFromPoint(MY_LOCATION)
.then(function () {
MY_LOCATION.Address = LOCATION.Address;
MY_LOCATION.Lat = LOCATION.Lat;
MY_LOCATION.Lng = LOCATION.Lng;
rechazar("Unable to retrieve your location. Using aleatory location.");
},
function (miError) {
rechazar("Unable to retrieve your location. " + miError);
});
});
}
});
}

/** Configuracion por defecto
* @returns {JSON} JSON
* */
function mapsOptions() {
/* Default Config */
return {
credentials: '', //credenciales de la API de Bing Maps
branch: 'release', //release or experimental
setLang: 'ES', //idioma
setMkt: 'es-ES', //cultura
ShowMap: { //modulo para mostrar mapas
Container: '',
Options: {
zoom: 16 //1-20
}
},
SuggestBox: { //modulo para sugerir direciones
searchText: '',
searchBox: '',
addressDestination: {
Street: '',
City: '',
State: '',
Country: '',
CountryISO: '',
PostCode: '',
FullAddress: ''
},
maxResults: 10,
hideAfterSelect: false,
autoFillSuggestResult: true,
fixedHeigh: false,
CallBackAfterSuggest: null,
situarMapa: false
},
DirectionsMap: {
directionsPanel: '',
directionsItinerary: ''
},
errorBox: '',
country: null,
detectLocation: false,
loadScript: true,
delay: 0
};
}

/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
*
* @param {object} obj1 origin
* @param {object} obj2 new object to merge
* @returns {object} obj3 a new object based on obj1 and obj2
*/
function _mergeOptions(obj1, obj2) {
let obj3 = {};
for (let attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (let attrname1 in obj2) { obj3[attrname1] = obj2[attrname1]; }
return obj3;
}

/**
* asignar valor a un elemento
* @param {String} elemId Id object
* @param {String} text Value
* @returns {void}
*/
function setValue(elemId, text) {
try {
if (text === undefined || text === null) text = '';
let elem = document.getElementById(elemId);
if (elem.localName !== 'span') {
elem.value = text;
}
else {
/* innerHTML works in firefox, innerText works in others.*/
if (detectarExplorador().Firefox !== true)
elem.innerText = text;
else
elem.innerHTML = text;
}
} catch (e) {
console.error(e);
return;
}
}

/**
* Ejecutar una funcion externa
* @param {any} func nombre de la funcion
* @param {any} data variable de la funcion
*/
function ExternalCallBack(func, data) {
if (data === undefined) data = null;
try {
if (typeof func === 'string') eval(func, data);
else func(data);
} catch (e) {
console.error(e.message);
}
}

/**
* enviar el foco a un elemento
* @param {String} idElemento id elemento
* @returns {boolean} devuelve true o false
*/
function SendFoco(idElemento) {
try {
document.getElementById(idElemento).focus();
} catch (e) {
return e;
}
}


/*capturar el evento, se debe de usar sobre todo si esta configurada la opcion de no autorellenar los datos
document.addEventListener('SuggestClick', function (e) {
console.log(e.detail.address); //contiene la direcion seleccionada
}, false);
*/
}


Consideraciones de seguridad

Es muy recomendable en el apartado de Enable Security que limites la ApiKey para que sólo se pueda utilizar desde una dirección web, o desde una dirección IP de un servidor. O por todas las páginas web dónde la estés utilizando o sus direcciones IP. Como puedes ver en mi ejemplo, la primera Key aún no le he habilitado la seguridad, pero en la segunda Key si está habilitada.

Eso es todo amigos

Espero que este script os salve la vida si estáis teniendo problemas con Google Maps, o que os la simplifique si ya estáis utilizando Bing Maps. Por favor se libre de comentar con cualquier duda que tengas al respecto, o mejora que veas que se le puede incluir.

Si quieres puedes ayudar con los gastos del servidor donde se aloja el script haciendo click en "compar". Son solo 180 PHP (Pesos Filipinas, menos de 3€ (euro) o un poco más de 3$ (dólares americanos)). Muchas gracias.

Actualización 22 Junio 2019

  • Ahora no es necesaria la inclusión de las credenciales.
  • Se pueden inicializar los módulos por separado.
  • Eliminado el delay por defecto.
  • Actualizado el blog y corregidos errores de escritura.

#javascript #APIs #maps #Git


Para descargar el archivo con el se agradece una haz click en el botón comprar ahora.

0 Comentarios

 
 
 
ApiKeys Registro
Cuenta

Archivo