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".
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 uservar notificationMsg =new Notification('Title',{
body:'I am the body text!'});});
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
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:
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 progressvar cacheFound = caches.match(event.request).then(function(response){if(response){//return the object cachedreturn response;}else{//if not, we make the normal requestreturn fetch(event.request);}});//we pass the promise
event.respondWith(cacheFound);});
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 objectssetTimeout(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});
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:
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 input file definimos un metodo que sera llamado "createPreview" cuando el input cambie
"createPreview" usan la API FileReader para leer el archivo
Creamos la instancia de FileReader y definimos 2 metodos para escuchar los eventos: "onload" y "onprogress"
onload se dispara cuando FileReader lee completamente el archivo, pero la imagen aun no ha sido cargada
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"
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.
El metedo encargado de la redimension es "drawImage" , despues con el metodo "toDataURL" obtenemos la nueva imagen redimensionada y la pasamos a Google streetview
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
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.
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
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:
Con un archivo físico con la extensión .svg
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:
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.
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”.
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/#/
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.
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:
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.
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 :
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”
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.
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 :
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”.
“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:
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
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:
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