2012-12-04 30 views
7

Câu hỏi của tôi là cách hiển thị hiệu quả các bản đồ tùy chỉnh lớn trong ứng dụng Phonegap ngoại tuyến, cho phép chúng được quét và thu phóng trơn tru trong khi vẫn hỗ trợ các thiết bị di động cũ hơn?Hiển thị và điều hướng bản đồ tùy chỉnh lớn ngoại tuyến bằng Phonegap

Tôi đang phát triển ứng dụng dành cho thiết bị di động có sử dụng vị trí địa lý để điều hướng các tuyến đường đi bộ ở những khu vực hẻo lánh, nơi người dùng sẽ không có tín hiệu và do đó có kết nối internet. Điều quan trọng là ứng dụng hoạt động tốt với Android 2.2+ (vì vậy SVG không phải là một tùy chọn) cũng như iOS4 +.

Tôi đã vẽ bản đồ vector tùy chỉnh bằng Adobe Illustrator ở độ phân giải phù hợp với từng tuyến, trung bình khoảng 2000x2000 pixel và lớn nhất trong số đó cho đến nay tạo ra hình ảnh 4000x2400 pixel.

Tôi đã chọn sử dụng Phonegap/JQM thay vì chỉ đơn giản vì tôi đến từ nền lập trình web và dường như là cách nhanh nhất để có giao diện người dùng và chạy mà không cần phải nghiên cứu mã gốc quá nhiều, mặc dù tôi đã viết một vài plugin Phonegap sử dụng mã gốc cho mục đích quản lý nguồn và màn hình.

Ứng dụng cần cho phép người dùng xoay quanh bản đồ (bằng cách kéo) và phóng to/thu nhỏ (bằng cách véo) trong khoảng từ 25% đến 200% kích thước hình ảnh gốc.

Hầu hết các thử nghiệm tôi đã thực hiện trên HTC Desire chạy Android 2.3.3 và HTC Wildfire chạy Android 2.2 vì đây có thể là một số thiết bị thông số thấp nhất mà ứng dụng sẽ phải chạy trên.

Tôi đã thử các cách tiếp cận khác nhau để hiển thị bản đồ (chi tiết bên dưới), nhưng cho đến nay mỗi mục đích đều không phù hợp vì mục đích sử dụng bộ nhớ của ứng dụng quá lớn, không gian lưu trữ yêu cầu làm cho ứng dụng quá lớn để tải xuống hoặc sử dụng CPU quá chuyên sâu gây lag khi panning/zooming.

Mọi đề xuất được đánh giá cao. Cảm ơn trước.


phương pháp tiếp cận Tôi đã thử: bản đồ

1. Hiển thị dạng raster PNG sử dụng thẻ

Đây là cách tiếp cận đầu tiên tôi đã cố gắng. Xuất hình ảnh 4000x2400 pixel từ Illustrator dưới dạng PNG-8 màu 128 dẫn đến tệp 746Kb. Tôi panned hình ảnh bằng cách định vị hoàn toàn nó liên quan đến khung nhìn và phóng to hình ảnh bằng cách mở rộng các thuộc tính chiều rộng/chiều cao của thẻ. Vấn đề với phương pháp này là ngay cả ở mức thu phóng 1: 1, ứng dụng Android đã sử dụng 60Mb RAM cho hình ảnh và phóng to 200% khiến điều này tăng 120Mb, khiến ứng dụng gặp sự cố trên HTC Wildfire.

2.Hiển thị các phần của raster PNG bằng cách sử dụng canvas HTML5

Để tránh vấn đề phóng to gây ra sự gia tăng tỷ lệ sử dụng bộ nhớ, tôi đã thử tải ảnh qua JS rồi sao chép phần ảnh được hiển thị trên canvas kích thước của khung nhìn, một cái gì đó như:

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

trong đó x, y là góc trên cùng bên trái trong hình ảnh nguồn được xác định bằng cách xoay và w, h là kích thước vùng trong hình ảnh nguồn xác định bởi mức độ phóng

Vấn đề ở đây là các hình ảnh bản đồ lớn mehow mất chất lượng trong khi trong bộ nhớ (Tôi chỉ có thể giả định có một số giới hạn bộ nhớ trên được dẫn đến dither), gây ra các bản đồ để trông méo mó trong ứng dụng: see here for an example screenshot

3. Bản đồ Hiển thị dạng vector sử dụng HTML5 canvas

Một chút Googling đã dẫn tôi khám phá ai2canvas, một plugin Illustrator cho phép bạn xuất tác phẩm nghệ thuật làm véc tơ được hiển thị trong canvas HTML5. Kết quả của việc xuất khẩu là một tập tin html có chứa một đoạn JS mà đại diện cho tất cả các đường dẫn trong illustrator như bezier đường cong. Xuất bản đồ 4000x2400 của tôi đã dẫn đến tệp html 550Kb chứa đường dẫn vector. Trong ứng dụng thử nghiệm của tôi, tôi đưa toàn bộ bản đồ vào canvas trong bộ nhớ (không được đính kèm với DOM) 4000x2400 pixel, sau đó sao chép các phần có liên quan của nó vào canvas có kích thước khung nhìn bằng cách sử dụng context.drawImage() với -memory canvas làm nguồn. Trên HTC Wildfire, mặc dù việc render ban đầu của tất cả các đường cong bezier đến canvas trong bộ nhớ mất khoảng 2000 mili giây, việc sao chép giữa các khung ảnh đủ nhanh để cho phép lướt và thu phóng mượt mà. Vấn đề là khi tôi xem xét việc sử dụng bộ nhớ của ứng dụng, nó đã sử dụng 120Mb cho canvas trong bộ nhớ một khi tất cả các vectơ đã kết xuất.

Tôi đã thử phương pháp thứ hai bằng cách sử dụng bản đồ vectơ; thay vì vẽ tất cả vectơ thành canvas lớn trong bộ nhớ, tôi đã thực hiện ứng dụng tính toán đường dẫn vector nào có thể nhìn thấy trong chế độ xem ở vị trí xoay/mức thu phóng hiện tại trong mỗi sự kiện kéo/kẹp và chỉ vẽ các vectơ nhìn thấy được canvas cỡ. Trong khi điều này giảm mức sử dụng bộ nhớ cần thiết xuống 10Mb, các chu kỳ CPU cần thiết để thực hiện các tính toán này trên mỗi chu kỳ kéo/pinch khiến ứng dụng tụt hậu rất nhiều trên điện thoại Android cũ mà không sử dụng được.

4. Hiển thị bản đồ sử dụng ẩn ốp lát

Sử dụng map tiler, tôi tạo ra gạch PNG cho bản đồ của tôi ở mức zoom từ 25% đến 100%. Trong ứng dụng thử nghiệm của tôi, tôi đã có thể lười biếng tải các gạch theo yêu cầu giảm mức sử dụng bộ nhớ và tạo ra trải nghiệm pan/zoom mượt mà ngay cả trên HTC Wildfire. Tôi nghĩ tôi đã tìm ra giải pháp cho đến khi tôi nhìn vào kích thước của APK được tạo ra: cho bản đồ 4000x2400 của tôi, bản đồ đã tạo ra 4Mb hình ảnh xếp kề. Hầu hết các bản đồ của tôi là khoảng 2000x2000 pixel, dẫn đến khoảng 2Mb gạch. Mã của ứng dụng thích hợp của tôi cộng với phí trên Phonegap là 2Mb khác. Mục đích của tôi là phát hành hàng loạt ứng dụng có sẵn trên thị trường Android/Apple, mỗi ứng dụng có khoảng 10 bản đồ, nhưng với mỗi bản đồ có trọng lượng từ 1-4Mb, do đó ứng dụng kết quả trở nên rất lớn tải về.

Trả lời

3

Trong trường hợp điều này được quan tâm đối với bất kỳ ai khác, tôi đã giải quyết vấn đề này bằng cách sử dụng bản đồ ốp lát cuối cùng, sử dụng công cụ gọi là pnqnq để tạo PNG 8 bit. Tập hợp các lát cho bản đồ 4000x2000 của tôi có kích thước khoảng 800K so với 4Mb đối với PNG-24, đây là kích thước có thể chấp nhận được đối với nội dung trong các ứng dụng Android và iOS của tôi.

Các vấn đề liên quan