我的问题是如何在离线的 Phonegap 应用程序中有效地显示大型自定义地图,允许它们平滑地平移和缩放,同时仍然支持旧的移动设备?
我正在开发一个移动应用程序,该应用程序涉及使用地理定位来导航偏远地区的步行路线,用户可能没有信号,因此没有互联网连接。重要的是该应用程序与 Android 2.2+(因此 SVG 不是一个选项)以及 iOS4+ 兼容。
我已经使用 Adobe 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 之间,因此生成的应用程序下载量非常大。