2012-12-04 10 views
7

La mia domanda è come visualizzare in modo efficiente mappe personalizzate di grandi dimensioni in un'applicazione offline di PhoneGap, consentendo loro di effettuare panoramiche e zoom senza intoppi continuando a supportare i dispositivi mobili meno recenti?Visualizzazione e navigazione di mappe personalizzate di grandi dimensioni offline tramite PhoneGap

Sto sviluppando un'applicazione mobile che prevede l'utilizzo della geolocalizzazione per navigare percorsi a piedi in aree remote in cui è probabile che l'utente non disponga di un segnale e quindi di una connessione Internet. È importante che l'app funzioni correttamente con Android 2.2+ (quindi SVG non è un'opzione) e iOS4 +.

Ho disegnato mappe vettoriali personalizzate utilizzando Adobe Illustrator a risoluzioni appropriate per ogni percorso, la media è di circa 2000x2000 pixel e il più grande dei quali finora produce un'immagine di 4000x2400 pixel.

Ho scelto di andare con Phonegap/JQM piuttosto che nativo semplicemente perché provengo da un background di programmazione web e mi è sembrato il modo più veloce per ottenere un'interfaccia utente attiva e funzionante senza dover scavare troppo nel codice nativo, anche se ho scritto un paio di plugin di PhoneGap usando il codice nativo per scopi di power e screen management.

L'applicazione deve consentire all'utente di eseguire panoramiche sulla mappa (trascinando) e zoom avanti/indietro (pizzicando) tra circa il 25% e il 200% della dimensione dell'immagine originale.

La maggior parte dei test che ho fatto è stata su un HTC Desire con Android 2.3.3 e un HTC Wildfire con Android 2.2 poiché questi sono probabilmente alcuni dei dispositivi con le specifiche più basse che l'applicazione dovrà eseguire sopra.

Ho provato vari approcci per visualizzare la mappa (dettagliata di seguito), ma finora tutti si sono dimostrati inadatti allo scopo perché l'utilizzo della memoria dell'app è troppo grande, lo spazio di archiviazione richiesto rende l'app troppo grande scaricare o l'utilizzo della CPU è troppo intenso causando lag quando si esegue il panning/zoom.

Eventuali suggerimenti molto apprezzati. Grazie in anticipo.


approcci che ho provato:

1. Visualizzare mappa raster come PNG utilizzando tag

Questo è stato il primo approccio che ho provato. L'esportazione dell'immagine di 4000x2400 pixel da Illustrator come PNG-8 a 128 colori ha dato come risultato un file 746Kb. Ho spostato l'immagine posizionandola in modo assoluto rispetto al viewport e ingrandito l'immagine ridimensionando gli attributi width/height del tag. Il problema con questo approccio era che anche con un livello di zoom 1: 1, l'applicazione Android usava 60Mb di RAM per l'immagine e lo zoom del 200% faceva aumentare di 120Mb, causando l'arresto anomalo dell'app su HTC Wildfire.

2.Visualizzare porzioni di PNG raster utilizzando la tela HTML5

Per evitare il problema dell'ingrandimento causando un aumento proporzionale dell'utilizzo della memoria, ho provato a caricare l'immagine tramite JS e quindi a copiare la parte dell'immagine da visualizzare su una tela. dimensione della finestra, qualcosa come:

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); 

dove x, y è l'angolo superiore sinistro all'interno dell'immagine sorgente definito dal panning e w, h è la dimensione area dell'immagine sorgente determinata dal livello di zoom

Il problema qui era che le immagini di mappe di grandi dimensioni erano così mehow perdere la qualità, mentre in memoria (posso solo supporre non c'è un limite di memoria superiore, che si traduce in dithering), provocando le mappe per appaiono distorte in app: see here for an example screenshot

3. mappa Visualizza come vettore utilizzando HTML5 canvas

Un po 'di Google su Google mi ha portato a scoprire ai2canvas, un plug-in di Illustrator che consente di esportare elementi grafici come vettori visualizzati in un canvas HTML5. Il risultato dell'esportazione è un file html contenente un blocco di JS che rappresenta tutti i percorsi in Illustrator come curve di bezier. Esportando la mia mappa 4000x2400 risultava un file HTML 550Kb contenente i percorsi vettoriali. Nella mia app di test, ho reso l'intera mappa su una tela in memoria (non collegata al DOM) di 4000x2400 pixel, quindi ho copiato le relative parti di essa su una tela di dimensioni viewport utilizzando context.drawImage() con la -memory canvas come fonte. Sull'HTC Wildfire, anche se il rendering iniziale di tutte le curve di Bezier sulla tela in memoria ha richiesto circa 2000 ms, la copia tra le tele è stata abbastanza veloce da consentire panoramiche e zoom uniformi. Il problema è stato quando ho esaminato l'utilizzo della memoria dell'app, utilizzando 120Mb per la tela in memoria dopo che tutti i vettori erano stati renderizzati.

Ho provato un secondo approccio utilizzando la mappa vettoriale; invece di rendere tutti i vettori su una grande tela in memoria, ho fatto in modo che l'app calcolasse quali percorsi vettoriali erano visibili all'interno del viewport all'attuale livello di posizione/zoom del pan durante ogni evento di trascinamento/pizzicamento e disegnava solo i vettori visibili nel viewport - tela di grandi dimensioni Mentre questo ha ridotto l'utilizzo di memoria richiesto a 10Mb, i cicli della CPU richiesti per eseguire questi calcoli su ogni ciclo di trascinamento/pizzico hanno reso l'app in ritardo sui vecchi telefoni Android che era inutilizzabile.

4. mappa display utilizzando offline piastrelle

Utilizzando map tiler, ho creato piastrelle PNG per le mie mappe a livelli di zoom dal 25% al ​​100%. Nella mia app di test, ero quindi in grado di caricare le piastrelle su richiesta riducendo l'utilizzo della memoria e producendo un'esperienza pan/zoom uniforme anche su HTC Wildfire. Ho pensato di aver trovato la soluzione fino a quando ho esaminato le dimensioni dell'APK prodotto: per la mia mappa 4000x2400, il piastrellista della mappa ha prodotto 4Mb di immagini di tile. La maggior parte delle mie mappe si aggira intorno ai 2000x2000 pixel, risultando in circa 2Mb di tessere. Il codice della mia applicazione più l'overhead di PhoneGap è un altro 2Mb.

La mia intenzione è di rilasciare una serie di app disponibili sui mercati Android/Apple, ognuna con un set di circa 10 mappe, ma con la piastrellatura ogni mappa pesa tra 1-4Mb così l'app risultante diventa molto grande Scaricare.

risposta

3

Nel caso in cui questo sia di interesse per chiunque altro, ho risolto questo problema utilizzando la piastrellatura della mappa alla fine, utilizzando uno strumento chiamato pnqnq per creare PNG a 8 bit vincolati a 256 colori. Il set di tessere risultante per la mia mappa 4000x2000 era di circa 800 K rispetto a 4 Mb per PNG-24, che era una dimensione accettabile per le risorse nelle mie applicazioni Android e iOS.

Problemi correlati