Mostrando entradas con la etiqueta javascript. Mostrar todas las entradas
Mostrando entradas con la etiqueta javascript. Mostrar todas las entradas

jueves, 6 de julio de 2017

Javascript reduce function


var users = [{
id: 1,
name: 'saul',
age: 2,
pets: ['cat','dog']
},
{
id: 1,
name: 'andrie',
age: 6,
pets: ['cat']
},
{
id: 1,
name: 'manuel',
age: 6,
pets: []
}];

users.reduce((accumulator, currentElement, index, array) => {
return accumulator.concat(currentElement.pets);
}, []);

//result
["cat", "dog", "cat"]


Reduce toma una callback y un valor initial opcional que es el acumulador que es pasado a la callback en cada iteracion. Entonces Reduce empieza a iterear por cada elemento llamando a la callback pasando el acumulador y el element sobre el cual se esta iterando.

La primera vez acumulador es un arreglo vacio por que es el valor inicial, las siguientes veces acumulador tiene el valor retornado por  la previa interacion. Asi es como al final de la iteracion reduce devuelve el valor de "accumulator".

Aqui un ejemplo usando objectos

var myArr = [
{ rating: 5 },
{ price: 200 },
{ distance: 10 }
];

var myObj = myArr.reduce(function( memo, item ) {
memo = Object.assign(memo, item);
return memo
}, {} );

//result
{rating: 5, price: 200, distance: 10}


Espero haber despejado dudas
















sábado, 31 de diciembre de 2016

Entendiendo la Web notification API

La Web notification API nos permite mandar notificaciones a los usuario a como lo hacen las app nativas.

Para usar primero necesitamos que el usuario de permiso con el siguiente codigo:


Notification.requestPermission(function(status) {  // status is "granted", if accepted by user
    var notificationMsg = new Notification('Title', { 
       body: 'I am the body text!'
    }); 
});

Puesdes ver la demo en este link:  https://saulburgos.github.io/practices/2017/webnotification/

 Una vez con el permiso, usamos el objecto Notificacion para crear un instancia del mensaje que queremos usar. Mas adelante si necesitamos verificar este permiso de nuevo podemos consulta la propiedad "permission", que puede tener los valores de : "default, granted, denied"

Notification.permission

Esta API comunmente se usa en conjunto con los services worker y push API, para notificar de la manera en como lo hacen las app nativas cuando no tienes la app abierta

links
https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
https://developer.mozilla.org/en/docs/Web/API/notification

viernes, 30 de diciembre de 2016

¿ Como saber con javascript si estas online ó offline ?

El objeto "navigation" puede ayudarnos con esto:

https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine

 Solo tenemos que consultar esta propiedad que nos devolvera un valor true/false.

window.navigator.onLine;

Su uso es:

if (navigator.onLine) {
  console.log('online');
} else {
  console.log('offline');
}
 

Tambien podemos escuchar un eventos para saber cuando hay conexión :

window.addEventListener("offline", function(e) { 
  console.log("offline");
});

window.addEventListener("online", function(e) { 
  console.log("online"); 
});

links

https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine



jueves, 29 de diciembre de 2016

Entendiendo la Cache API


Comunmente esta API es usada en conjunto con la API Service worker, pero puedes usarlo independientemente aunque no he encontrado un ejemplo de su uso fuera de esta API. Segun la definicion se usa para guardar objectos "Request" y "Response", esto significa que puedes dar las peticiones que haces al server y tambien las respuestas del server.

Una parte importante a saber que casi todos los metodos de esta API usan promesas. Para crear un espacio donde cachear todos nuestros assets solo necesitamos llamar este metodo del objecto "caches"

caches.open('test-cache').then(function(cache) {
  // Cache is created and accessible
});

El nombre 'test-cache' es una namespace o identificador de la cache que hemos creado. De esta manera podemos usarla luego.

Para agregar elementos a la cache creada se usa comunmente los metodos "Add" y "addAll".

cache.add('/sw-test/index.html').then(function() {
  //request have been added to the cache
});

cache.addAll(['/', '/images/logo.png']).then(function() {
  //requests have been added to the cache
});

La diferencia es que en la segunda se pasa un arreglo de urls. Algo que destacar aqui es que usar el metodo "add" es lo mismo que usar fetch de formal normal con put de esta manera:

fetch(url).then(function (response) {
  if (!response.ok) {
    throw new TypeError('bad response status');
  }
  return cache.put(url, response);
});

O peticiones personalizadas con el object "Request" de esta forma:

cache.add(new Request('/page/1', { /* request options */ }));
 
"add" and "addAll" son como atajos del metodo "put" por que con este metodo pones en cache usando key/value de esta manera:

fetch(url).then(function (response) {
  return cache.put(url, response);
});

Revisar la cache

 Para revisar que hemos puesto en la cache primero necesitamos abrirla y despues explorar los elementos usando el metodo "keys"de esta manera:

caches.open('test-cache').then(function(cache) { 
 
  cache.keys().then(function(cachedRequests) { 
    // [] Array of all of caches keys
  });
});

Para buscar dentro se usan los metodos "match", "matchAll":

caches.open('test-cache').then(function(cache) {
  cache.match('/page/1').then(function(matchedResponse) {
    console.log(matchedResponse);
  });
});

En el ejemplo anterior, estamos buscando el objecto en cache que correspondo con la peticion a 'page/1'

Otros usos comunes serian leer y buscar:

caches.open('test-cache').then(function(cache) {
  cache.delete('/page/1');
});

caches.keys().then(function(cacheKeys) { 
  console.log(cacheKeys); // Get all the namespace created
});

caches.delete('test-cache').then(function() { 
  console.log('Cache successfully deleted!');  
});

Dentro de un service worker, el proceso seria algo asi:

  • El service worker intercepta todas las peticiones al server, ya sean ajax o cargar otras paginas web.
  • Una vez interceptada la peticion, revisamos en nuestra cache si esa peticion ya esta en la cache
  • Si es asi devolvemos el objecto en cache.
  • Si no dejamos que la peticion siga su curso, al terminar la metemos al cache.

Ejemplo de esto:

//trigger on url changes and requests to the server
serviceWorker.addEventListener('fetch', function(event) { 
 //search in the cache for the request that is in progress
 var cacheFound = caches.match(event.request).then(function(response) {
  
  if (response) {
   //return the object cached
    return response;
  } else {
   //if not, we make the normal request
   return fetch(event.request); 
  }  
 });

 //we pass the promise 
 event.respondWith(cacheFound);

});

Aqui he hecho un ejemplo del uso de la cache API sin un service worker

Links

https://developer.mozilla.org/en-US/docs/Web/API/Cache
https://davidwalsh.name/cache



Entendiendo la Promise API

Las promesas son ahora la manera preferida de trabajar y en el futuro sera muy pocos los casos en los que necesitaras una callback. jQuery tiene su propio sistema de promesas.

Pero ahora tenemos una API promise nativa que podemos usar. Su uso es muy sencillo:

var promise = new Promise(function(resolveFn, rejectFn) { 
 
 //you can do here operations and later decided if resolve or reject the promise
 //using the objects
 setTimeout(function() { 
  resolveFn(10);

 }, 3000);

});

//when is resolve
promise.then(function(result) {
 console.log(result);
});

//when is rejected
promise.catch(function(result) {
 console.log(result);
});

Despues de haber instanciado el objecto "Promise" tienes los metodos "resolveFn" y "rejectFn" los cuales puedes ejecutar cuando tu quieras en un futuro, los cuales van a ejecutar los metodos pasados a "then" y "catch".

Un interesante metodo de "Promise" es "all", el cual recibe un arreglo de promesas y ejecuta "then" cuando todas han sido "resolve".

Promise.all([promise1, promise2]).then(function(results) {
 // Both promises resolved
})
.catch(function(error) {
 // One or more promises was rejected
});

Link

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://davidwalsh.name/promises



Entendiendo la Fetch API

Ahora ya no usamos Ajax para hacer peticiones al server ahora usamos Fetch. Por que ? por que nos permite usar promesas en lugar de callbacks, permitiendo un codigo mas limpio.

Una peticion con fetch basica es de la siguiente manera:

fetch('./api/some.json').then(function(respond){
    //exito
}).catch(function(err) { 
    //Error en la peticion
});

La promesa se mira en accion con los metodos "then" y "catch", a los cuales se le pasa metodos para ser ejecutados cuando terminen.

Then : Es ejecutado cuando la peticion termina correctamente.
catch: Es ejecutado cuando en la peticion ocurrio un error.

Fetch retorna un objecto stream cuando la peticion es exitosa, el cual tiene muchos metodos para usar. Puedes consultarlos aqui. El ejemplo completo seria asi:

fetch('./api/some.json').then(function(response) { 
   
    if (response.status !== 200) { 
      console.log('Looks like there was a problem. Status Code: ' + 
        response.status); 
      return; 
    }

    // Examine the text in the response 
    response.json().then(function(data) { 
      console.log(data); 
    }); 

}).catch(function(err) { 
  console.log('Fetch Error :-S', err); 
});

Otras propiedades interesantes del objecto response son:

fetch('users.json').then(function(response) {  
    console.log(response.headers.get('Content-Type'));  
    console.log(response.headers.get('Date'));

    console.log(response.status);  
    console.log(response.statusText);  
    console.log(response.type);  
    console.log(response.url);  
});

El objecto response puede ser de varios tipos para una mejor descripcion visita este link.


Adicionalmente puedes usar los objectos "Request" y "Header" para personalizar los peticiones fetch. Tomando un ejemplo de david walsh, seria asi:

// Create an empty Headers instance
var headers = new Headers();

// Add a few headers
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');

// Check, get, and set header values
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');

// Delete a header
headers.delete('X-My-Custom-Header');

// Add initial values
var headers = new Headers({
  'Content-Type': 'text/plain',
  'X-My-Custom-Header': 'CustomValue'
});

var request = new Request('https://davidwalsh.name/some-url', {
  headers: new Headers({
    'Content-Type': 'text/plain'
  })
});

fetch(request).then(function() { /* handle response */ });

Es una manera facil y alternativa del uso de ajax.

Links:

https://davidwalsh.name/fetch
https://developers.google.com/web/updates/2015/03/introduction-to-fetch
https://developer.mozilla.org/en/docs/Web/API/Fetch_API
https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/ 



miércoles, 16 de noviembre de 2016

Libro Google maps Javascript - Capítulo 6 : Hacer un preview de Google streetview desde un input file


Volver al indice




Hace pocos dias tuve la necesidad de crear una previsualización de un panorama google streetview usando un input file, esto fue para el proyecto de Tours virtuales . Por que muchos usuarios estaban subiendo imagenes incorrectas y hasta que eran procesadas podian ver los resultados finales. Esta era tediso asi que , he creado una funcionalidad de previsualización.

 En el siguiente link puedes ver el resultado:

https://jsfiddle.net/SaulBurgos/rg5o213b/3/

Los pasos son los siguientes:
  1.  En el input file definimos un metodo que sera llamado "createPreview" cuando el input cambie
  2. "createPreview" usan la API FileReader para leer el archivo
  3. Creamos la instancia de FileReader y definimos 2 metodos para escuchar los eventos: "onload" y "onprogress"
  4. onload se dispara cuando FileReader lee completamente el archivo, pero la imagen aun no ha sido cargada
  5. Para cargar la imagen creamos una imagen con la Image  API, al igual que con FileReader podemos definier un metodo para correrlo cuando la imagen ha sido cargada con "onload"
  6. Despues solo usamos canvas para crear un objecto donde poner esta imagen. Esta parte es la mas importante por que aqui se redimensiona la imagen a 1024x512. De esta manera evitamos que el navegador se congele, por si el usuario ingresa resolusiones muy grandes.
  7. El metedo encargado de la redimension es "drawImage" , despues con el metodo "toDataURL" obtenemos la nueva imagen redimensionada y la pasamos a Google streetview




http://www.paneek.net/





lunes, 12 de septiembre de 2016

Como sincronizar el scroll de 2 divs con hijos de tamaños diferentes en Javascript


Para que este post pueda ser encontrado en ingles pondre esta linea:

How do I synchronize the scroll position of two divs  with different height ?

Hoy en el trabajo nos sentamos un buen amigo mio y yo e hicimos este pequeño  demo de como funciona. La verdad que todo el credito se lo lleva mi amigo Hod es su algoritmo . Yo solo ayude con la parte de Javascript y unas pocas cosas

Espero que a alguien le sea util.





viernes, 19 de agosto de 2016

Javascript : testeando Page Visibility API

Un ejemplo practico de uso de Page Visibility API , es para saber si el usuario cambia de tab en el misma ventana del navegador, pero no funciona si el usuario se pasa a otra ventana. El soporte para esta api es muy decente : http://caniuse.com/#feat=pagevisibility

Posibles usos
  • Pausar video o sonidos
  • Detener animaciones que nadie esta viendo
  • Detener llamadas al servidor si nadie las vera

Ahora un ejemplo

Visita este link y veras como el video es detenido cuando cambias de tab. 

Link:






lunes, 15 de agosto de 2016

Si programas tienes que usar una guia de estilos para tu codigo...

Si actualmente estas programando y no estas usando una guía de estilo para tu código de acuerdo al lenguaje que usas,  estas cometiendo un gran error...

Una guía de estilo de código en palabras simples es como tu código luce , como lo ven los demás. Si miras todo el código que has escrito hasta ahora podrás notar un cierto patrón, ese es tu propio estilo.
El problema con esto es que no es entandar y la mayoría de las veces solo tu podrás entenderlo.

No serial genial que todos escribieran el código como tu lo haces ?  .... Por esa razón mi buen amigo es que existen las guía de estilo de código, para que todos podamos leer y entender el código de los demás.

Una guía de estilo de código por lo general tiene lo siguiente:

  • Como y cuando usar comentarios
  • Como usar y cuanto espacio e indentación deberías de utilizar
  • Nombres adecuados para tus variables y funciones
  • Como agrupar tu código
  • Que técnicas usar o cuales no, dependiendo del lenguaje
Si tu objetivo es trabajar en una gran empresa, necesitas aprender los estilos de código para cada lenguaje que usas. Es un gran dolor de cabeza cuando un nuevo programador quiere escribir código a como le da la gana, Si tu eres uno de estos seguramente no vas a durar mucho.

Una rápida búsqueda en Google puede ayudarte a encontrar los estilos que buscas, pero a continuación podre algunos





miércoles, 25 de mayo de 2016

Que es SVG y como usarlo en paginas web

SVG es un formato de imagen para dibujos vectoriales, el mismo tipos de archivos que usan los diseñadores gráficos con Adobe Illustrador.  Gracias a los nuevos estandares web podemos usar este tipo de formatos de imagen y aprovechar todos los beneficios.

Beneficios

  • Tamaño de archivo muy pequeño y comprimido
  • La image se puede ver perfectamente en cualquier resolución de pantalla ya que puede ser escalado sin problemas, pudiendo verse perfecto en resoluciones retina display.
  • Tamaño del archivo reducido.


Normalmente ese tipo de archivos son creados con alguna herramienta de dibujos vectoriales como Adobe Illustrador. Ahora mismo existen muchos editores online de SVG donde puedes crearlos y editarlos.

Independientemente de la herramientas uses, tu puedes usar un SVG de 2 maneras:


  1. Con un archivo físico con la extensión .svg
  2. O con el codigo SVG que es similar a este:
Con cualquiera de los 2 puedes trabajar.  Para usar el SVG solo tienes que usar la etiqueta img como con cualquier imagen normal y con CSS puedes controlar el tamaño. Ejemplo:


Tambien puedes usar un SVG como fondo de un elemento con CSS.

.container {
    width: 100px;
    height: 82px;
    background: url(yourFile.svg);
}

También otra opciones es usar la etiqueta “object”. Ejemplo:


<object type="image/svg+xml" data="namefile.svg">Your browser does not support SVGs</object>

Usando el código SVG


Descarga el Siguiente archivo:


Después abre el archivo con tu editor de texto, por ejemplo yo estoy usando sublime text, cuando abras el archivo verás el código SVG que crea la imagen. Este código lo puedes copiar y pegar directamente en un archivo HTML y verás como el SVG aparece, El navegador lo cargara automáticamente.

Los archivos SVG pueden ser optimizados ya que como puedes ver en el código del archivo del “Che.svg” hay muchas etiquetas adicionales. Puedes usar la siguiente herramienta para esto.


También puedes dar estilo individualmente a cada elemento del SVG, tan solo tienes que asignar clases para poder dar tus estilos. Ten en cuenta que para dar estilo a los SVG tienes que usar propiedades CSS especiales para ellos, los cuales tienes que buscar en google por ejemplo.



Si quieres conocer un poco más en detalle cada elemento dentro del SVG tag , te sugiero que visites este link:



Adicionalmente esta tabla te ayudará a entender lo que puedes hacer con los SVG dependiendo la manera en como lo insertes en tu página web.



Lo que puedes hacer
Object
Inline
Img
Background-image
CSS Manipulation
Yes
Yes
Some inline
Some inline
JS Manipulation
Yes
Yes
No
No
SVG Animation
Yes
Yes
Yes
Yes
Interactive SVG Animation
Yes
Yes
No
No

Usando Javascript con SVG


También podemos manipular los SVG con javascript como lo haríamos con un objeto normal HTML, podemos usar javascript puro o jquery para esto. En el siguiente ejemplo que encontre internet puedes ver cómo se selecciona el elemento y después se cambia su propiedad “fill”.



Si quieres una manipulación más avanzada con los SVG te recomienzo las siguientes librarias:



Habiendo escrito todo lo anterior, Deberías de ir considerando de usar svg en todos tus iconos y logos de tus proyectos web. Si por alguna razon aun no estas convencido visita este link :

http://talks.brennaobrien.com/svg/#/


links






jueves, 21 de enero de 2016

Libro Google maps Javascript - Capítulo 5 : Guardar y cargar tu overlays parte 2


Volver al indice



Siguiente paso

Suponiendo que los datos enviados al servidor fueron guardados con éxito en una base de datos,  ahora viene la segunda parte de este proceso, recrear todos los overlays y nuestro mapa basados en estos datos, básicamente el proceso será inverso, a esto se le llama : Deserialización.

Los datos almacenados en la base de datos por lo general son obtenidos por medio de un método AJAX o algún servicio web, el cual debe devolver un objeto JSON  de preferencia,  con todos los datos correspondientes. Para los siguientes ejemplos vamos a suponer que el método AJAX nos ha devuelvo el siguiente objeto basado en los ejemplos anteriores.

{
"overlays":[{"position":"","type":"","id":"","draggable":"","title":"","description":""}],
"map":{"zoom":"","bounds":"","mapType":"","type":"map"}
}

Los datos de los overlay se encuentran en la propiedad “overlays”, que es un arreglo de objetos y los datos de nuestro mapa se encuentran en la propiedad “map”. Vamos a crear un método llamado “FakeAjax” el cual nos devolverá este objeto simulando un llamado AJAX al servidor, Para los siguientes ejemplos vamos usar como punto de partida el archivo de práctica número “29” el cual contiene creado el método “FakeAjax”.

Normalmente los objetos JSON que son devueltos como respuesta del servidor, vienen en formato cadena por lo tanto tienes que parsear esa cadena para convertirla a un objeto Javascript por ejemplo usando el método jQuery.parseJSON()

Deserializar Marker


En nuestro archivo de practica numero “29” tenemos el método “FakeAjax”, que nos devuelve un objeto con toda la información que necesitamos recrear. El cual ejecutamos en el evento “idle” de nuestro mapa.

google.maps.event.addListenerOnce(map, 'idle', function() {
    var data = FakeAjax();
});   

Ahora necesitamos iterar sobre el arreglo de objetos que contiene la información que necesitamos en la propiedad “overlays”.


google.maps.event.addListenerOnce(map, 'idle', function() {
    var data = FakeAjax();
    for (var i = 0 ; i < data.overlays.length ; i++)
    {
        switch(data.overlays[i].type)
        {
              case "marker":
                //marker
                break;
         case "polyline":
                //polyline
         break;
         case "rectangle":
                //rectanlge
            break;
         case "circle":
                //cirlce
         break;
         case "polygon":
                //polygon
         break
        }
    }
});

Usando un ciclo FOR iteramos sobre el arreglo de objetos y para cada elemento del arreglo usamos su propiedad “type”, para saber que tipo de overlay  se necesita deserializar usando un switch javascript. Ahora vamos a crear un método llamado “DeserializeMaker”.


google.maps.event.addListenerOnce(map, 'idle', function() {
    var data = FakeAjax();
    for (var i = 0 ; i < data.overlays.length ; i++)
    {
        var objectDeserialized;
        switch(data.overlays[i].type)
        {
              case "marker":
            objectDeserialized = DeserializeMaker(data.overlays[i]);
             break;
               case "polyline":
            //polyline
             break;
       case "rectangle":
             //rectanlge
              break;
              case "circle":
            //cirlce
              break;
              case "polygon":
                //polygon
              break;
              }
        objectDeserialized.setMap(map);
    }
});

function DeserializeMaker (object) {
    var position = object.position.split(',');
    var latLng = new google.maps.LatLng(position[0],position[1]);
    var marker = new google.maps.Marker({
        position: latLng,
        draggable:object.draggable
    });
    return marker;
}

En nuestro método “DeserializeMarker” estamos recibiendo como parámetro el elemento del arreglo actual sobre el cual se está iterando, este objeto tiene las propiedades que previamente habíamos serializado para recrear el marker, en este caso solo es “position” el cual es una cadena de texto con los valores LatLng de la position del marker  separados por coma,  usando el método split podemos obtener estos datos como un arreglo. Recuerda que el primer valor es Lat y el segundo es Lng. Este es un ejemplo del objeto que estamos recibiendo:

Object {
    position: "-39.198205,-56.162109",
    type: "marker",
    id: 1,
    draggable: true
}

Después creamos nuestros objetos Latlng y Marker usando las clases de Google Maps, pasando como parámetro los valores obtenidos de la propiedad “position”. Nuestro método devuelve el objeto marker creado, el cual es asignado en la variable “objectDeserialized”, en esta variable asignaremos cada objeto creado por nuestros métodos y al final de cada ciclo FOR usaremos el método “setMap” para asignar el objeto creado al mapa ya que todos los overlays comparten el este metodo.

Deserializar rectangle


Con el overlay rectangle vamos a usar el método “DeserializeRectangle”. A partir de ahora solo haré referencia al código referente al switch para evitar repetir líneas de código continuamente para mostrar los siguientes ejemplos. Ya que el resto de codigo sera el mismo.

switch(data.overlays[i].type)
{
      case "marker":
        objectDeserialized = DeserializeMaker(data.overlays[i]);
    break;
    case "polyline":
        //polyline
    break;
    case "rectangle":
        objectDeserialized = DeserializeRectangle(data.overlays[i]);
    break;
    case "circle":
        //circle
    break;
    case "polygon":
        //polygon
    break;
}


function DeserializeRectangle (object) {   
    var bounds = object.bounds.split(',');
    var swLatLng = new google.maps.LatLng(bounds[0],bounds[1]);
    var neLatLng = new google.maps.LatLng(bounds[2],bounds[3]);
    var rectangleBounds = new google.maps.LatLngBounds(swLatLng,neLatLng);
    var rectangle = new google.maps.Rectangle({
        bounds: rectangleBounds,
        editable:object.editable
    });
    return rectangle;
}

Nuestro método está recibiendo como parámetro el siguiente objeto :

Object {
    bounds: "-31.615966,-43.813477,-27.80021,-38.803711",
    type: "rectangle",
    id: 2,
    editable: true
}

La propiedad “bounds” contiene las coordenadas Latlng en formato cadena necesarios para crear el objeto bounds que necesitamos para recrear nuestro overlay, usando el método split convertimos los datos a un arreglo y los usamos para crear los objetos Latlng. Recuerda que estos puntos vienen en el siguiente orden : "lat_lo, lng_lo, lat_hi ,lng_hi" después de haber usado “toUrlValue” para serializarlo.

Con estos puntos LatLngs creamos nuestro objeto “bounds”, el que es usado para crear nuestro overlay.

Deserializar Polyline


Para el overlay Polyline usaremos el método “DeserializePolyline”

switch(data.overlays[i].type)
{
      case "marker":
        objectDeserialized = DeserializeMaker(data.overlays[i]);
    break;
    case "polyline":
        objectDeserialized = DeserializePolyline(data.overlays[i]);
    break;
    case "rectangle":
        objectDeserialized = DeserializeRectangle(data.overlays[i]);
    break;
    case "circle":
        //circle
    break;
    case "polygon":
        //polygon
    break;
}

Este método recibirá el siguiente objeto como parámetro :

Object {
    path: "-39.605688,-49.042969,-39.707187,.....",
    type: "polyline",
    id: 3,
    draggable: true
}

La propiedad “path” contiene todos nuestros puntos separados por comas en formato cadena,  por lo tanto debemos de crear a partir de ellos un objeto MVCArray par recrear nuestro path.


El método encargado para de esta tarea será “DeserializeMvcArray” :

function DeserializeMvcArray(stringLatlng) {
    var arrayPoints = stringLatlng.split(',');
    var mvcArray = new google.maps.MVCArray();
    for(var i= 0; i < arrayPoints.length; i+=2)
    {
        var latlng = new google.maps.LatLng(arrayPoints[i],arrayPoints[i+1]);
        mvcArray.push(latlng);
    }   
    return mvcArray;
}

Este método recibe el path en formato cadena, después creamos un arreglo a partir de esta cadena con el método split. Usando la clase MVCArray  creamos un objeto,  al cual dentro del ciclo FOR, agregamos cada punto Latlng creado, por medio del método push. También nota que nuestro ciclo for itera cada 2 elementos en el arreglo, esto es debido a que el primer elemento es Lat y el siguiente Lng y así sucesivamente, al terminar el ciclo for regresará el objeto MVCArray Creado. Ahora solo nos resta incluir este método en “DeserializePolyline”.

function DeserializePolyline (object) {   
    var mvcArray = DeserializeMvcArray(object.path);
    var polyline = new google.maps.Polyline({
        path: mvcArray,
        draggable:object.draggable,
        editable:true
    });
    return polyline;
}

En este método sólo nos resta pasar nuestro mvcArray creado a nuestro overlay para crear la polyline.


Deserializar Polygon

Para polygon utilizaremos de nuevo el método “DeserializeMvcArray”, debido a que el path del objeto serializado polygon también es una cadena con los valores separados por comas.

Object {
    path: "-36.421282,-50.581055,-37.822802....",
    type: "polygon",
    id: 5,
    draggable: true
}

Crearemos  un método llamado “DeserializePolygon” :

switch(data.overlays[i].type)
{
    case "marker":
        objectDeserialized = DeserializeMaker(data.overlays[i]);
    break;
    case "polyline":
        objectDeserialized = DeserializePolyline(data.overlays[i]);
    break;
    case "rectangle":
        objectDeserialized = DeserializeRectangle(data.overlays[i]);
    break;
    case "circle":
        //circle
    break;
    case "polygon":
        objectDeserialized = DeserializePolygon(data.overlays[i]);
    break;
}
function DeserializePolygon (object) {   
    var mvcArray = DeserializeMvcArray(object.path);
    var polygon = new google.maps.Polygon({
        paths: mvcArray,
        draggable:object.draggable,
        editable:true
    });
    return polygon;
}



Nuestro método recibe el objeto serializado y crea el MVCArray usando la propiedad path con el método “DeserializeMvcArray”, el que después pasamos como parámetro para crear nuestro overlay.

Deserializar Circle


Para circle usaremos el método llamado “DeserializeCircle” y este es el objeto que recibirá este método :

Object {
    center: "-29.688053,-56.513672",
    radius: 388514.2326,
    type: "circle",
    id: 4,
    draggable: true
}

Y en nuestro switch

switch(data.overlays[i].type)
{
      case "marker":
        objectDeserialized = DeserializeMaker(data.overlays[i]);
    break;
    case "polyline":
        objectDeserialized = DeserializePolyline(data.overlays[i]);
    break;
    case "rectangle":
        objectDeserialized = DeserializeRectangle(data.overlays[i]);
    break;
    case "circle":
        objectDeserialized = DeserializeCircle(data.overlays[i]);
    break;
    case "polygon":
        objectDeserialized = DeserializePolygon(data.overlays[i]);
    break;
}


function DeserializeCircle (object) {   
    var center = object.center.split(',');
    var centerLatLng = new google.maps.LatLng(center[0],center[1]);
    var circle = new google.maps.Circle({
        center: centerLatLng,
        radius: object.radius,
        draggable:object.draggable,
        editable:true
    });
    return circle;
}

La propiedad “center” es la que contiene nuestro punto Latlng en formato cadena, la cual convertimos a un objeto Latlng Google Maps la cual usamos en las opciones junto con “radius”.

Actualizar Map


Hasta ahora hemos deserializado todos los tipos de overlays, pero todavía nos queda actualizar el mapa con el nivel de zoom , tipo de mapa y  el lugar exacto donde estaba el usuario cuando los datos fueron guardados. Usaremos el método llamado “UpdateMap”.

google.maps.event.addListenerOnce(map, 'idle', function() {
    var data = FakeAjax();
    for (var i=0;i < data.overlays.length;i++)
    {
        var objectDeserialized;
        switch(data.overlays[i].type)
        {
            case "marker":
                objectDeserialized = DeserializeMaker(data.overlays[i]);
            break;
            case "polyline":
                objectDeserialized = DeserializePolyline(data.overlays[i]);
            break;
            case "rectangle":
                objectDeserialized = DeserializeRectangle(data.overlays[i]);
            break;
            case "circle":
                objectDeserialized = DeserializeCircle(data.overlays[i]);
            break;
            case "polygon":
                objectDeserialized = DeserializePolygon(data.overlays[i]);
            break;
        }
        objectDeserialized.setMap(map);
    }
    UpdateMap(data.map);
});   

“UpdateMap” es llamado fuera del ciclo FOR debido a que los datos que necesitamos no se encuentran  en un arreglo, sino en un objeto simple en la propiedad “map” con las siguientes propiedades:

Object {
    zoom: 5,
    bounds: "-41.261381,-63.325123,-24.786843,-33.793873",
    mapType: "hybrid",
    type: "map"
}

Y nuestro método es el siguiente:

function UpdateMap (object){
    var bounds = object.bounds.split(',');
    var swLatLng = new google.maps.LatLng(bounds[0],bounds[1]);
    var neLatLng = new google.maps.LatLng(bounds[2],bounds[3]);
    var mapBounds = new google.maps.LatLngBounds(swLatLng,neLatLng);
    map.fitBounds(mapBounds);
    map.setZoom(object.zoom);   
    map.setMapTypeId(google.maps.MapTypeId[object.mapType.toUpperCase()]);
}

Como lo hemos hecho anteriormente primero creamos nuestro objeto bounds a partir de la propiedad “bounds” en formato cadena, la cual asignamos con el método “fitBounds” del objeto “map” , seguido asignamos el zoom y el tipo del mapa.

Al asignar el tipo de mapa estamos usando las constantes de mapa  de la API que comúnmente son de esta manera :

google.maps.MapType.HYBRID
google.maps.MapType.ROADMAP
google.maps.MapType.SATELLITE
google.maps.MapType.TERRAIN

En nuestro código es un tanto diferente ya que nos basamos en que los objetos en javascript son arreglos asociativos,  por lo tanto en nuestra línea de código podemos acceder al valor por medio de su “keyname” y usando el método “toUpperCase” de javascript, nos aseguramos de que sean en letras mayúsculas. Normalmente esto podría hacerse por medio de un switch pero creo que de esta manera nos ahorramos unos lineas de código.

Hasta aquí ha sido todo en este capítulo si quieres ver el ejemplo completo puedes abrir el archivo de práctica en la carpeta número “30”. Adicional a este tambien deberias ver el archivo de ejemplo número “31” el cual contiene una versión modificada con algunos campos adicionales y evento click en la lista de la izquierda para ubicar el overlay.


Usar GeoJson es una buena option


Una buena option adicional a todo lo visto antes es usar el formato GeoJson , el cual te permite guardar geometrias en una estructura estandar. Recomiendo leer sobre como crear and trabjar con este tipo de objectos por que de esa manera puedes exportar tus datos a muchos lados y muchas base de datos ya soportan este formato.

Para darte una idea de como funciona visita este editor online de GeoJson y revisa como el objecto es armado. 

En google tambien han escrito este articulo sobre GeoJson muy bueno sobre como usar este estandar dentro de google maps. 
Una vez que entiendas como crear y manipular GeoJson recomiendo que estudies esta libreria http://turfjs.org/  , con ella podras hacer todo tipo de operaciones que pensabas que eran imposibles.


Ejemplos Adicionales 

 


Obtener  puntos Latlng contenidos dentro de un bounds


Aunque  este libro no cubre lenguajes del lado del servidor, considero que el siguiente caso es muy común entre el desarrollo de aplicaciones de mapas, por tal razón he decidido incluirlo.

Habrá algunas ocasiones donde solo queremos mostrar overlays o markers que solo se encuentran dentro del actual viewport del mapa. Para lograr esto solo tienes que obtener el bounds del mapa el cual contiene un método llamado :

bounds.contains(latLng:LatLng)  : El cual devuelve “true” si el Latlng que has pasado como parámetro se encuentra dentro de él.

Usando la API de Google Maps es realmente fácil saber esto,  pero esto  quiere decir que tienes que cargar todos los puntos Latlng antes en algun arreglo e iterar en cada uno. Lo conveniente seria que solo obtuvieras desde tu base de datos los puntos latlng que se encuentran dentro de este bounds.

Por ejemplo imagina que tienes un en tu base de datos una tabla llamada “markers” y esta tabla  contiene 2 campos llamados “Latitude” y “longitud”, donde previamente han sido guardados estos valores para 1000 registros, en lugar de cargar estos mil registros de una sola vez en tu mapa , solo queremos obtener los que se encuentran dentro del bounds del mapa actual.

Para realizar esto tienes que enviar al servidor tu coordenadas del bounds actual del mapa, esto lo puedes hacer por medio del método :

bounds.toUrlValue(precision?:number) : que devuelve una cadena con los puntos en el siguiente orden : "lat_lo,lng_lo,lat_hi,lng_hi" .

Una vez que obtengas estos datos del lado del servidor solo tienes que ejecutar la siguiente consulta SQL, que sólo devolverá los registros con los Latlng que se encuentran dentro de bounds indicado.

SELECT * FROM markers
WHERE    
Latitude < "lat_hi" AND
Latitude > "lat_lo" AND
Longitude < "lng_hi" AND
Longitude > "lng_lo";

La consulta anterior solo funcionara con puntos en norteamerica, si quieres un consulta que funcione nivel mundial por favor visitar el siguiente link de stackoverflow

http://stackoverflow.com/questions/4834772/get-all-records-from-mysql-database-that-are-within-google-maps-getbounds/20741219#20741219

Hay muchas respuestas recomiendo que verifiques todas y descubras cual funciona para ti. (Yo probe la del usuario vladimir)


Cálculo de áreas y distancias


Google Maps pone a nuestra disposición la librería “Geometry Library”  con la cual podremos realizar cálculos de datos geométricos sobre la superficie de la Tierra. Similar a otras librerías  con las que hemos trabajado anteriormente, tenemos que incluirla en nuestro proyecto de la siguiente manera:

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry"></script>

El uso de los métodos de esta librería es tan sencillo  como solamente  llamar al método estático deseado para realizar la operación. He preparado 2 ejemplos de cómo usar esta librería para calcular áreas y distancias entre puntos en el mapa. Animo al lector a revisar el código para su comprender cómo funciona.

En el ejemplo de práctica en la carpeta número “32”, puedes encontrar un ejemplo de cómo se  calcula la distancia entre 2 puntos. Al mover los markers sobre el mapa podrás ver como en el panel izquierdo se actualiza la distancia entre estos puntos, la cual es devuelta en metros.

Y en el ejemplo de práctica en la carpeta número “33”, podras encontrar el código de ejemplo de como calcular el área de las overlays en Google Maps, las cuales son expresadas en metros cuadrados. Si dibujas una overlay, podrás ver como se actualiza el panel izquierdo con la información del área. Para las polyline se esta calculando la distancia total  en metros.

EasyLocator


Hace un tiempo atras cree un jquery plugin que te permite crear un mapa con puntos en el mapa de manera rapida y sencilla, por favor hecha un vistado talvez te pueda ser muy util.

Jquery plugin google maps EasyLocator

-------------------------------------------------------------------------------------


http://www.paneek.net/