Visualización y navegación de grandes mapas personalizados sin conexión con Phonegap

Mi pregunta es cómo mostrar eficientemente grandes mapas personalizados en una aplicación de Phonegap sin conexión, lo que les permite ser panorámicos y zoom sin problemas mientras sigue soportando dispositivos móviles más antiguos?

Estoy desarrollando una aplicación móvil que implica el uso de la geolocalización para navegar rutas de senderismo en áreas remotas donde es probable que el usuario no tenga una señal y por lo tanto una conexión a Internet. Es importante que la aplicación funcione bien con Android 2.2+ (por lo que SVG no es una opción), así como con iOS4 +.

He dibujado mapas de vectores personalizados usando Adobe Illustrator en resoluciones apropiadas para cada ruta, siendo el promedio de 2000×2000 píxeles y el mayor de los cuales hasta ahora resulta en una imagen de 4000×2400 píxeles.

He elegido ir con Phonegap / JQM en lugar de nativo simplemente porque vengo de un fondo de programación web y parecía la forma más rápida de obtener una interfaz de usuario en funcionamiento sin necesidad de profundizar en código nativo demasiado, aunque he Escrito un par de Phonegap plugins utilizando código nativo para los propósitos de poder y la gestión de la pantalla.

La aplicación debe permitir al usuario desplazarse alrededor del mapa (arrastrando) y acercar / alejar (entre pellizcar) entre un 25% y un 200% del tamaño de la imagen original.

La mayor parte de las pruebas que he hecho ha sido en un HTC Desire con Android 2.3.3 y un HTC Wildfire con Android 2.2, ya que es probable que sean algunos de los dispositivos de especificaciones más bajas que la aplicación va a tener que ejecutar.

He intentado varios acercamientos para exhibir el mapa (detallado abajo), pero hasta ahora cada uno ha demostrado no apto para el propósito ya sea porque el uso de memoria de la aplicación es demasiado grande, el espacio de almacenamiento requerido hace que la aplicación sea demasiado grande para descargar o El uso de la CPU es demasiado intenso, causando retraso al realizar panorámicas / zoom.

Cualquier sugerencia muy apreciada. Gracias por adelantado.


Enfoques que he intentado:

1. Mostrar el mapa como raster PNG usando etiqueta

Este fue el primer enfoque que intenté. Exportar la imagen 4000×2400 píxeles de Illustrator como un PNG-8 de 128 colores resultó en un archivo de 746Kb. Hice una panorámica de la imagen posicionándola absolutamente en relación con la ventana de visualización y ampliando la imagen al escalar los atributos de anchura / altura de la etiqueta. El problema con este enfoque fue que incluso con un nivel de zoom de 1: 1, la aplicación Android utilizaba 60Mb de RAM para la imagen y el zoom en 200% causaba que aumentara 120Mb, causando que la aplicación se bloqueara en el HTC Wildfire.

2. Mostrar porciones de PNG raster usando lienzo HTML5

Para evitar el problema del acercamiento que causa un aumento proporcional en el uso de la memoria, intenté cargar la imagen vía JS entonces copiando la porción de la imagen a ser exhibida a un lienzo el tamaño de la ventana de visualización, algo así como:

var canvas = $('canvas#mycanvas'); canvas.width = $(window).width; canvas.height = $(window).height; ... var img = new Image(); img.src = “map.png”; ... var context = canvas[0].getContext("2d"); context.drawImage(img, x, y, w, h, 0, 0, canvas.width, canvas.height); 

Donde x, y es la esquina superior izquierda dentro de la imagen de origen definida por panoramización yw, h es el tamaño de área dentro de la imagen de origen determinada por el nivel de zoom

El problema aquí era que las grandes imágenes de mapa estaban de alguna manera perdiendo calidad mientras en la memoria (sólo puedo suponer que hay algún límite de memoria superior que está dando lugar a dithering), haciendo que los mapas parezcan distorsionados en la aplicación: ver aquí un ejemplo de captura de pantalla

3. Mostrar el mapa como vector utilizando lienzo HTML5

Un poco de Googling me llevó a descubrir ai2canvas, un complemento de Illustrator que le permite exportar ilustraciones como vectores mostrados en un lienzo HTML5. El resultado de la exportación es un archivo html que contiene un fragmento de JS que representa todas las rutas en ilustrador como curvas de bezier. Exportar mi mapa 4000×2400 resultó en un archivo html de 550Kb que contiene las rutas vectoriales. En mi aplicación de prueba, procesé todo el mapa en un lienzo en memoria (no conectado al DOM) de 4000×2400 píxeles, luego copié las porciones relevantes de él a un lienzo de tamaño de pantalla utilizando context.drawImage () Como la fuente. En el HTC Wildfire, aunque el render inicial de todas las curvas del bezier hasta el lienzo en la memoria tomó alrededor de 2000 ms, copiar entre lienzos fue lo suficientemente rápido para permitir una panorámica suave y zoom. El problema fue cuando miré el uso de la memoria de la aplicación, que estaba utilizando 120Mb para el lienzo en memoria una vez que todos los vectores se han convertido.

Intenté un segundo acercamiento usando el mapa del vector; En lugar de renderizar todos los vectores a un gran lienzo en memoria, hice que la aplicación calculara qué vías vectoriales eran visibles dentro de la ventana de visualización en el nivel de panorámica / zoom actual durante cada evento de arrastrar / pellizcar y sólo dibujar los vectores visibles a la ventana de visualización – lona clasificada. Mientras que esto redujo el uso de memoria requerido a 10Mb, los ciclos de CPU requeridos para realizar estos cálculos en cada ciclo de arrastrar / pellizcar hicieron que la aplicación se retrasara tanto en los teléfonos androides antiguos que era inutilizable.

4. Mostrar el mapa utilizando mosaicos sin conexión

Utilizando el mosaico de mapas , creé mosaicos PNG para mis mapas a niveles de zoom del 25% al ​​100%. En mi aplicación de prueba, pude entonces cargar los azulejos a la demanda, reduciendo el uso de memoria y produciendo una experiencia de panorámica / zoom uniforme incluso en el HTC Wildfire. Pensé que había encontrado la solución hasta que miré el tamaño del APK producido: para mi mapa 4000×2400, el fabricante del mapa produjo 4Mb de imágenes del azulejo. La mayoría de mis mapas están alrededor de 2000×2000 píxeles, resultando en aproximadamente 2Mb de azulejos. El código de mi aplicación correcta, además de la sobrecarga Phonegap es otro 2Mb.

Mi intención es lanzar una serie de aplicaciones disponibles en los mercados de Android / Apple, cada uno con un conjunto de alrededor de 10 mapas, pero con mosaico cada mapa pesa entre 1-4 Mb para que la aplicación resultante se convierte en una descarga muy grande.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.