{"id":106,"date":"2022-09-05T05:38:15","date_gmt":"2022-09-05T05:38:15","guid":{"rendered":"http:\/\/34.172.140.203\/wordpress\/?p=106"},"modified":"2022-10-26T16:23:45","modified_gmt":"2022-10-26T16:23:45","slug":"google-maps-firebase","status":"publish","type":"post","link":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/2022\/09\/05\/google-maps-firebase\/","title":{"rendered":"Google Maps + Firebase"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/storage.googleapis.com\/strapi_bucket-1\/Captura_de_Pantalla_2022_09_07_a_la_s_12_50_30_p_m_f5a5c736f3\/Captura_de_Pantalla_2022_09_07_a_la_s_12_50_30_p_m_f5a5c736f3.png\" alt=\"foto\"\/><\/figure>\n\n\n\n<p>Firebase es una plataforma de desarrollo de aplicaciones que permite crear y desarrollar aplicaciones m\u00e1s r\u00e1pidamente. Respaldado por Google y en el que conf\u00edan millones de empresas de todo el mundo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfQu\u00e9 son los geodatos?<\/h2>\n\n\n\n<p>Los geodatos son simplemente datos que contienen alg\u00fan componente espacial, como las coordenadas de ubicaci\u00f3n, que representan una realidad geogr\u00e1fica. Son producto de una observaci\u00f3n y generalizaci\u00f3n del entorno geogr\u00e1fico complejo y permiten su representaci\u00f3n y an\u00e1lisis espacial en un contexto definido.<\/p>\n\n\n\n<p>Los elementos fundamentales de los geodatos son (Aronoff, 1989):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Ubicaci\u00f3n espacial, posici\u00f3n geogr\u00e1fica del objeto de acuerdo a un sistema de coordenadas.<\/li><li>Atributos, elemento cuantificable del objeto geogr\u00e1fico que permite su caracterizaci\u00f3n y lo define apropiadamente.<\/li><li>Temporalidad, escala de tiempo en el cual se observa el objeto para cuantificar e identificar cambios significativos.<\/li><\/ul>\n\n\n\n<p>Existen diferentes formas de guardar los geodatos,&nbsp;<\/p>\n\n\n\n<p>Firebase nos ofrece diferentes soluciones, a lo largo de esta publicaci\u00f3n se tratar\u00e1n las principales ventajas de usar Firebase con Google Maps.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Laboratorio de C\u00f3digo<\/h2>\n\n\n\n<p>Objetivo: Crear un Mapa Colaborativo de Google Maps con una base de datos en Firebase&nbsp;<\/p>\n\n\n\n<p>Creaci\u00f3n del Proyecto:&nbsp;<\/p>\n\n\n\n<p>Creamos el proyecto desde la consola de Firebase, que es accedida desde&nbsp;<a href=\"https:\/\/console.firebase.google.com\/\">https:\/\/console.firebase.google.com\/<\/a>.<\/p>\n\n\n\n<p>Desarrollo de C\u00f3digo:<\/p>\n\n\n\n<p>Para comenzar, crea un archivo nuevo en un editor de texto, nosotros usamos Visual Studio Code y gu\u00e1rdalo como index.html.<\/p>\n\n\n\n<p>Crear un mapa b\u00e1sico<\/p>\n\n\n\n<p>Este c\u00f3digo carga la API de Maps JavaScript y muestra el mapa en pantalla completa. Tambi\u00e9n carga la biblioteca de visualizaci\u00f3n, que servir\u00e1 para crear un mapa de calor. Reemplaza APIKEY por la clave de API de tu aplicaci\u00f3n, que puede ser generada desde&nbsp;<a href=\"https:\/\/console.cloud.google.com\/apis\/credentials\">https:\/\/console.cloud.google.com\/apis\/credentials<\/a>, donde se debe de tener un proyecto creado as\u00ed como una cuenta de facturaci\u00f3n activada..<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/KNE1CgVnXpJI-DTEwIoPPtVX9jpUBmG1SHcAuxxbM3ICu9oO-g4Btm1s6IG5k6Ux1RYXKjVYQtYwDOROtuIx6RLe7IkEHFIxPMtq-YVK8XGJlPZASfgd4ZimM074ZL3I3gckZH0d-ljpRGOW9vt0UyUiw9fj2_lbH0340sDsoHD9FW7b_tX12WslKA\" alt=\"\"\/><\/figure>\n\n\n\n<p>Agregar Firebase<\/p>\n\n\n\n<p>Para que esta aplicaci\u00f3n sea colaborativa, debes almacenar los clics en una base de datos externa a la que todos los usuarios puedan acceder. Firebase Realtime Database se adapta a este prop\u00f3sito y no requiere conocimientos de SQL.<\/p>\n\n\n\n<p>Generaci\u00f3n de la Configuraci\u00f3n de Firebase<\/p>\n\n\n\n<p>La generaci\u00f3n de configuraci\u00f3n de firebase se tiene que hacer&nbsp;<a href=\"https:\/\/console.firebase.google.com\/\">https:\/\/console.firebase.google.com\/<\/a>&nbsp;en donde se tiene que crear un proyecto; para lo que es necesario configurar o tener configurada una cuenta de facturaci\u00f3n. Para este laboratorio se cre\u00f3 el proyecto con el plan Blaze, haciendo uso del nivel gratuito. Una vez creado el proyecto, podremos agregar nuestra aplicaci\u00f3n; si es web, android o IOS.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/WUnVih_ZWqOc2trjd-CIizuJ80nlFjQDsaSftuWexPH8UAOJqRAEtMjtvCF4-o1g8i3majMHQ5pxGWH7xJWy_veXTViH5XidFT9XIRFQ2YHKwrvTenKOOlxCM1gifSdI_50OCPxHd57CmSWessCWhlj_MIX7PtwWCrnbzPrqfO35mN7nk739muD5jA\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/pTxQSYeHS8f_lSw9jgH24On-usF5mAMXALLp4grvUJyDwHIyYZ83StCjy-r0U9NN7jajAW4o_gwnqE6FqjayaLIQ11cNpUVFTkgvZ-CvBGSdq1BkE6ynL4k08jyxCWL5hkV8VixFYh1SdK1XPZNNw3VPZEezTuzA-MSTCbiEqwBgIck4Pr6Pf_Wtww\" alt=\"\"\/><\/figure>\n\n\n\n<p>Para poder utilizar firebase , se tendra que crear un proyecto en firebase, se puede hacer en un nivel gratuito (Blaze). Si creas una app nueva, puedes asignarle un nombre nuevo y una URL de Firebase personalizada que termine en firebaseIO.com. Por ejemplo, puedes nombrar el mapa de Firebase de tu app con la URL https:\/\/janes-firebase-map.firebaseIO.com. Puedes usar esta URL para vincular la base de datos a tu aplicaci\u00f3n de JavaScript.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/b7X-83On2_IOWRvmiGBK_0KLW5eOaP6aFJgvrDKosQbr131SO24aXayGCAdEcqJhh7ACivWXr-hXdcGQRcRSSOujjSoJPPxYA2hnwhUdBvKbbfsbJEUGRzjq9G0iDMsSFWv9P_H9OLVeMMFnyckxP3vWBeK2Yx_5QlrXI1UGXZloM2CycSUK4QjbDg\" alt=\"\"\/><\/figure>\n\n\n\n<p>Dependiendo de la versi\u00f3n en la que se encuentre Firebase, nos recomendar\u00e1 hacer la importaci\u00f3n por script o bien mediante un manejador como npm o yarn para proyectos con Node.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/tSNqArw09Yw50giQKGWGEZdRN51avnz2zPDoeKktvJzyWqC3JABD3sDBuOrn_WPolt1AlCxiWAoESsfbUibgNbHc9wF_sfljQOie_3HLobXlp-7O7ikDZMNpMUmXEHuBT6Jzp3SzYnHVfz1gP6tVuzUsmgXNiC7M0zbpAri7jz1N_Q4OJXMqUDoIeQ\" width=\"624\" height=\"356\"><\/h2>\n\n\n\n<p>C\u00f3mo muestra un ejemplo de la configuraci\u00f3n obtenida; adem\u00e1s fue necesario activar la base de datos; en donde se utiliz\u00f3 en tiempo real.&nbsp;<\/p>\n\n\n\n<p>Almacenamiento de datos de clics en Firebase<\/p>\n\n\n\n<p>Por cada clic del mouse en el mapa, el siguiente c\u00f3digo crea un objeto de datos global y almacena su informaci\u00f3n en Firebase. Este objeto registra datos como su latitud y longitud (latlng) y la marca de tiempo del clic, as\u00ed como un ID \u00fanico del navegador que cre\u00f3 el clic.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/TZCi9tjvVM3-uga5e-CxGtrSqFpTGusv7Z0ZVS2AHdk19WQttR0wRR2JrilrN8N2n6ihMIeEEJmbLrRM9GG--2KD5KnObnaWzxvkbgA6c21CpmRVX7BZhwBmHY3ZtlUUBKdZq1ngA6FGztpxxPlhEdEtTBX1th09WUAh_hZ8qOTJwDsazciTovUsTA\" alt=\"\"\/><\/figure>\n\n\n\n<p>El siguiente c\u00f3digo registra un ID de sesi\u00f3n \u00fanico para cada clic, lo que ayuda a controlar la tasa de tr\u00e1fico en el mapa de acuerdo con las reglas de seguridad de Firebase.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/hnyXAzFVeti6OwHxYNDvbIm40ghkQXLfn463YovhE8Wqk6iQ5hWo9EzV0YvFCfGLDpDKB2D6cuzl51Ue1G2V4uJvg_cHkVxHcv7sNa_FFMDsXKYkG94YYhiqE0T3fqIuGU38NBFOalImv-S_4ZTr3vT6_ZGkh4pg2RWKVuUrzlUoPuIV3gJnGCJ-fA\" alt=\"\"\/><\/figure>\n\n\n\n<p>La siguiente secci\u00f3n de c\u00f3digo&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>detecta clicks en el mapa, que agrega un elemento secundario a tu base de datos de Firebase. Cuando esto ocurre, la funci\u00f3n snapshot.val() obtiene los valores de datos de la entrada y crea un nuevo objeto LatLng.. Cuando se produce un clic, la app registra una marca de tiempo y, luego, agrega un elemento secundario a tu base de datos de Firebase.<\/li><li>Borra en el mapa los clics que tengan m\u00e1s de 10 minutos en tiempo real.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/YCaLj5Pyegm39NbM-TlR-u9v9pOyBmKDbydZbeN6p1eKDpW7-g0LHBcoA4zsovl6QVSFRs_hFogWj_bnrIF5sn-mVGfAfA7m704KXksKpXd6EvVRyoNTPuBKH-paxtT2kOY0h2l5vlSnJGGbALLQefLcb0P0hu4k5qGdACYEVtmx73NG5TPVf-YvFQ\" alt=\"\"\/><\/figure>\n\n\n\n<p>Inicializaci\u00f3n del mapa con propiedades iniciales y el mapa de calor<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/8TUJj-oAXUOrkBQgtCjHwXiqS70oFDAeQUZKd-G73B61QFb0DGIOydhQ59lCGgoJfpS-6dAFH8O_QQr3nH3X1Ik-NGY4I0XD1iDVKhq8d45PUy3uZQd5cDyHZ4o6Mlc29OhC_p3Fsl__vD-Hgtr7txwdBQs4eLkMXrj_e5Zmjsgz7K66L2kdZgScgQ\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Resultado<\/h2>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/GMb1MppyYKhKIsjRjod6PCrHg-F8erVaku7234n-JPMqU0eKmyF6Zy82o6_b_FabP8oM11UKIfpZh83pcN2-S7DHs3BFDr7xmBxwau6qB7C8gkbvKpwXxscuOWlw-ASOLUtuV8mnP65saz9MPxvMIers-unfjjprH2PGgsYpf6eg-gHuMYIqkgu-2A\" alt=\"\"\/><\/figure>\n\n\n\n<p>Tambi\u00e9n podemos ver el resultado directamente desde firebase<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/rDYvMcg4PdOR_I2t9ExkrXCWdTmsduv6KqMGOBKHdzh8RkDFn-lpC-OSF08ZNyG4jhaA-vpCqvrFPvVOONdaTrimuR5JIeUU4Rbbqli5iBnabU-OSksyt6MvKI_b2Ngi1CsBHUjTjh2DxS10xRY-yTvC_Hp6ZwxGEJuXEz9jDg55kIw7VcL5SfCtjw\" alt=\"\"\/><\/figure>\n\n\n\n<p>Finalmente el c\u00f3digo completo tambien disponible en el repositorio de github:&nbsp;<a href=\"https:\/\/github.com\/eSourceCapital\/ESC-WS-Firebase-and-maps\">https:\/\/github.com\/eSourceCapital\/ESC-WS-Firebase-and-maps<\/a>&nbsp;<\/p>\n\n\n\n<p>&lt;!DOCTYPE&nbsp;html&gt;<\/p>\n\n\n\n<p>&lt;html&gt;<\/p>\n\n\n\n<p>&nbsp; &lt;head&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;style&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; #map {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; height: 100%;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/* Opcional: tama\u00f1o completo. *\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; html,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; body {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; height: 100%;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; margin: 0;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; padding: 0;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;\/style&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;!&#8211; Importamos firebase (8.10)&#8211;&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script src=&#8221;https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-app.js&#8221;&gt;&lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script src=&#8221;https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-auth.js&#8221;&gt;&lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script src=&#8221;https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-firestore.js&#8221;&gt;&lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script src=&#8221;https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-database.js&#8221;&gt;&lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &lt;\/head&gt;<\/p>\n\n\n\n<p>&nbsp; &lt;body&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;!&#8211; Agregamos el div del mapa&#8211;&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;div id=&#8221;map&#8221;&gt;&lt;\/div&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; defer<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; src=&#8221;https:\/\/maps.googleapis.com\/maps\/api\/js?key=[APIKEY]&amp;libraries=visualization&amp;callback=initMap&#8221;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &gt;&lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;script&gt;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Firebase config block.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; const firebaseConfig = {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;[change]<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; };<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; firebase.initializeApp(firebaseConfig);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; var db = firebase.firestore();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* objeto a guardar en firebase<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; var data = {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; sender: null,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; timestamp: null,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; lat: null,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; lng: null<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; };<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function makeInfoBox(controlDiv, map) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ CSS<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var controlUI = document.createElement(&#8220;div&#8221;);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.boxShadow = &#8220;rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.backgroundColor = &#8220;#fff&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.border = &#8220;2px solid #fff&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.borderRadius = &#8220;2px&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.marginBottom = &#8220;22px&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.marginTop = &#8220;10px&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.style.textAlign = &#8220;center&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlDiv.appendChild(controlUI);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ CSS: mensaje.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var controlText = document.createElement(&#8220;div&#8221;);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlText.style.color = &#8220;rgb(25,25,25)&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlText.style.fontFamily = &#8220;Roboto,Arial,sans-serif&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlText.style.fontSize = &#8220;100%&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlText.style.padding = &#8220;6px&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlText.textContent = &#8220;el mapa muestra los \u00faltimos 10 min.&#8221;;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; controlUI.appendChild(controlText);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Funci\u00f3n Principal, se llama a la autenticaci\u00f3n<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* @param {function()} onAuthSuccess &#8211; se llama cunado la autenticaci\u00f3n fue exitosa.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function initAuthentication(onAuthSuccess) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; firebase<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .auth()<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .signInAnonymously()<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .catch(<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function (error) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(error.code + &#8220;, &#8221; + error.message);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { remember: &#8220;sessionOnly&#8221; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; firebase.auth().onAuthStateChanged(function (user) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (user) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.sender = user.uid;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onAuthSuccess();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Creamos un objeto mapa con un listener de clicks y un mapa de calor.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function initMap() {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var map = new google.maps.Map(document.getElementById(&#8220;map&#8221;), {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; center: { lat: 0, lng: 0 },<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; zoom: 3,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; disableDoubleClickZoom: true,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; streetViewControl: false,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ creamos un div para el infowindows<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var infoBoxDiv = document.createElement(&#8220;div&#8221;);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; makeInfoBox(infoBoxDiv, map);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; map.controls[google.maps.ControlPosition.TOP_CENTER].push(infoBoxDiv);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Agregamos el Listener.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; map.addListener(&#8220;click&#8221;, function (e) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.lat = e.latLng.lat();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.lng = e.latLng.lng();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addToFirebase(data);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Creamos el mapa de calor.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var heatmap = new google.maps.visualization.HeatmapLayer({<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data: [],<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map: map,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; radius: 16,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ mandamos a llamar la autenticaci\u00f3n<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; initAuthentication(initFirebase.bind(undefined, heatmap));<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Configure un Firebase con eliminaci\u00f3n de clics anteriores a expiryMs<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* @param {!google.maps.visualization.HeatmapLayer} heatmap Mapa de calor<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function initFirebase(heatmap) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ 10 minutos antes.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var startTime = new Date().getTime() &#8211; 60 * 10 * 1000;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Referencia a los clicks en Firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var clicks = firebase.database().ref(&#8220;clicks&#8221;);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Escuchamos clicks y los agregamos al mapa de calor.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; clicks<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .orderByChild(&#8220;timestamp&#8221;)<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .startAt(startTime)<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .on(&#8220;child_added&#8221;, function (snapshot) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Obtenemos el click de firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newPosition = snapshot.val();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var point = new google.maps.LatLng(<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newPosition.lat,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newPosition.lng<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsedMs = Date.now() &#8211; newPosition.timestamp;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Agregamos el punto al mapa de calor.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; heatmap.getData().push(point);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Solicitamos entradas dentro de los ultimos 10 minutos.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var expiryMs = Math.max(60 * 10 * 1000 &#8211; elapsedMs, 0);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Configure el tiempo de espera del cliente para eliminar el punto despu\u00e9s de un tiempo determinado.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; window.setTimeout(function () {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Eliminamos los puntos<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapshot.ref.remove();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, expiryMs);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Elimine los datos antiguos del mapa de calor cuando se elimine un punto de firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; clicks.on(&#8220;child_removed&#8221;, function (snapshot, prevChildKey) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var heatmapData = heatmap.getData();<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var i = 0;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapshot.val().lat != heatmapData.getAt(i).lat() ||<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapshot.val().lng != heatmapData.getAt(i).lng()<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i++;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; heatmapData.removeAt(i);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Actualiza la ruta last_message\/ con el timestamp actual.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* @param {function(Date)} addClick despu\u00e9s de actualizar el timestamp del \u00faltimo mensaje,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; esta funci\u00f3n se llama con el timestamp actual para agregar el<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; click a firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function getTimestamp(addClick) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; var ref = firebase.database().ref(&#8220;last_message\/&#8221; + data.sender);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; ref.onDisconnect().remove(); \/\/ Elimina la referenccia de firebase .<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Establecer el timestamp.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; ref.set(firebase.database.ServerValue.TIMESTAMP, function (err) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (err) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(err);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref.once(<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8220;value&#8221;,<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function (snap) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addClick(snap.val()); \/\/ Agrega el click con el timestamp.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function (err) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.warn(err);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; \/**<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* Agregar clicks a firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* @param {Object} data Los datos a agregar a firebase.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; Contiene lat, lng, sender (quien envia) y el timestamp (fecha y hora).<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp;*\/<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; function addToFirebase(data) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; getTimestamp(function (timestamp) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ agrega el timestamp.<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.timestamp = timestamp;<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ref = firebase<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .database()<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ref(&#8220;clicks&#8221;)<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .push(data, function (err) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (err) {<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.warn(err);<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; &nbsp; });<\/p>\n\n\n\n<p>&nbsp; &nbsp; &nbsp; }<\/p>\n\n\n\n<p>&nbsp; &nbsp; &lt;\/script&gt;<\/p>\n\n\n\n<p>&nbsp; &lt;\/body&gt;<\/p>\n\n\n\n<p>&lt;\/html&gt;<\/p>\n\n\n\n<p>Laboratorio Original en&nbsp;<a href=\"https:\/\/developers.google.com\/maps\/documentation\/javascript\/firebase\">https:\/\/developers.google.com\/maps\/documentation\/javascript\/firebase<\/a>, es importante considerar que &nbsp;la versi\u00f3n original es para Firebase 5.3. Mientras que la versi\u00f3n empleada por eSource fue firebase 8.10. Revisar el historial de versiones de firebase antes de decidir utilizar cualquier funcionalidad de dicha plataforma:&nbsp;<a href=\"https:\/\/firebase.google.com\/support\/releases\">https:\/\/firebase.google.com\/support\/releases<\/a>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Firebase es una plataforma de desarrollo de aplicaciones que permite crear y desarrollar aplicaciones m\u00e1s r\u00e1pidamente. Respaldado por Google y en el que conf\u00edan millones de empresas de todo el mundo. \u00bfQu\u00e9 son los geodatos? Los geodatos son simplemente datos que contienen alg\u00fan componente espacial, como las coordenadas de ubicaci\u00f3n, que representan una realidad geogr\u00e1fica. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":175,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-106","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articulos-de-interes"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/106","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=106"}],"version-history":[{"count":1,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/106\/revisions"}],"predecessor-version":[{"id":107,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/106\/revisions\/107"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/media\/175"}],"wp:attachment":[{"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog-esource.daxosline.com.co\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}