7

我的问题是如何在离线的 Phonegap 应用程序中有效地显示大型自定义地图,允许它们平滑地平移和缩放,同时仍然支持旧的移动设备?

我正在开发一个移动应用程序,该应用程序涉及使用地理定位来导航偏远地区的步行路线,用户可能没有信号,因此没有互联网连接。重要的是该应用程序与 Android 2.2+(因此 SVG 不是一个选项)以及 iOS4+ 兼容。

我已经使用 Adob​​e Illustrator 以适合每条路线的分辨率绘制了自定义矢量图,平均约为 2000x2000 像素,而迄今为止最大的图像为 4000x2400 像素。

我选择使用 Phonegap/JQM 而不是原生,因为我来自网络编程背景,这似乎是启动和运行用户界面的最快方法,而无需过多研究原生代码,尽管我已经使用本机代码编写了几个 Phonegap 插件,用于电源和屏幕管理。

应用程序需要允许用户在原始图像大小的大约 25% 到 200% 之间平移(通过拖动)和放大/缩小(通过捏合)地图。

我所做的大部分测试都是在运行 Android 2.3.3 的 HTC Desire 和运行 Android 2.2 的 HTC Wildfire 上进行的,因为这些可能是应用程序必须运行的最低规格设备。

我已经尝试了各种显示地图的方法(详情如下),但到目前为止,每种方法都被证明不适合目的,因为应用程序的内存使用量太大,所需的存储空间使应用程序太大而无法下载或CPU 使用率太高,导致平移/缩放时出现延迟。

任何建议都非常感谢。提前致谢。


我尝试过的方法:

1.使用标签将地图显示为光栅PNG

这是我尝试的第一种方法。将 4000x2400 像素的图像从 Illustrator 导出为 128 色 PNG-8 会生成一个 746Kb 的文件。我通过相对于视口绝对定位图像来平移图像,并通过缩放标签的宽度/高度属性来缩放图像。这种方法的问题在于,即使在 1:1 的缩放级别下,Android 应用程序使用 60Mb 的 RAM 来存储图像,放大到 200% 会导致这增加 120Mb,从而导致应用程序在 HTC Wildfire 上崩溃。

2. 使用 HTML5 画布显示光栅 PNG 的部分

为了避免放大导致内存使用量成比例增加的问题,我尝试通过 JS 加载图像,然后将要显示的图像部分复制到视口大小的画布上,例如:

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

其中 x,y 是由平移定义的源图像内的左上角,w,h 是由缩放级别确定的源图像内的区域大小

这里的问题是大地图图像在内存中以某种方式失去了质量(我只能假设有一些内存上限导致抖动),导致地图在应用程序中看起来失真:请参阅此处以获取示例屏幕截图

3. 使用 HTML5 画布将地图显示为矢量

通过谷歌搜索,我发现了 ai2canvas,这是一个 Illustrator 插件,可让您将艺术品导出为 HTML5 画布中显示的矢量。导出的结果是一个 html 文件,其中包含一大块 JS,它将 illustrator 中的所有路径表示为贝塞尔曲线。导出我的 4000x2400 地图会生成一个 550Kb 的 html 文件,其中包含矢量路径。在我的测试应用程序中,我将整个地图渲染到 4000x2400 像素的内存画布(未附加到 DOM),然后使用 context.drawImage() 将其相关部分复制到视口大小的画布中内存画布作为源。在 HTC Wildfire 上,虽然所有贝塞尔曲线到内存画布的初始渲染花费了大约 2000 毫秒,但画布之间的复制速度足以实现平滑的平移和缩放。

我尝试了使用矢量图的第二种方法;我没有将所有矢量渲染到内存中的大画布,而是让应用程序计算在每个拖动/捏合事件期间在当前平移位置/缩放级别的视口中哪些矢量路径是可见的,并且只将可见矢量绘制到视口大小的画布。虽然这将所需的内存使用量减少到 10Mb,但在每个拖动/捏合循环上执行这些计算所需的 CPU 周期使得应用程序在旧的 android 手机上滞后太多以至于无法使用。

4.使用离线平铺显示地图

使用map tiler,我为我的地图创建了 PNG 切片,缩放级别从 25% 到 100%。在我的测试应用程序中,我能够按需延迟加载磁贴,从而减少内存使用并产生平滑的平移/缩放体验,即使在 HTC Wildfire 上也是如此。在查看生成的 APK 的大小之前,我以为我已经找到了解决方案:对于我的 4000x2400 地图,地图拼贴器生成了 4Mb 的平铺图像。我的大部分地图都在 2000x2000 像素左右,产生大约 2Mb 的图块。我的正确应用程序的代码加上 Phonegap 开销又是 2Mb。

我的意图是在 Android/Apple 市场上发布一系列可用的应用程序,每个应用程序都有一组大约 10 张地图,但平铺每张地图的重量在 1-4Mb 之间,因此生成的应用程序下载量非常大。

4

1 回答 1

3

如果其他人对此感兴趣,我最后通过使用地图平铺解决了这个问题,使用名为pnqnq的工具创建限制为 256 种颜色的 8 位 PNG。生成的 4000x2000 地图的瓦片集大小约为 800K,而 PNG-24 为 4Mb,这对于我的 Android 和 iOS 应用程序中的资产来说是可接受的大小。

于 2013-02-03T15:21:29.607 回答