5

我必须在 iOS5/6 (iPhone) 上实现一个非常自定义的平铺地图图层/视图,它将平铺作为图像和/或数据 (JSON) 从服务器加载。它就像谷歌地图,但在某些方面非常具体,所以我不能轻易使用以下解决方案:

  1. 谷歌地图
  2. route-me(由 MapBox 使用)
  3. CATiledLayer结合UIScrollView

问题是:由于我的具体规格,那里的解决方案都没有真正帮助我。如果您认为,有合适的解决方案,请告诉我!!!

如果没有:
帮我为我的情况找到最好的解决方案!!!

“但为什么我不能使用这些漂亮的解决方案呢?”
有一些限制,必须知道:

  1. 我们只使用 3 个缩放级别(0,1 和 2)

  2. 每个图块在下一个缩放级别中有 9 个子图块(= 缩放因子3不像大多数其他工具包那样有4 个子图块= 缩放因子2

  3. 第一层的初始大小为(以像素/点表示是一半)768*1024。
    第二层比第二层宽和高三倍(zoomfactor 3!!!) -> 2304*3072
    第三层比第二层同样宽和高 -> 6912*9216

  4. 来自服务器的每个图块都是 256x256 像素

  5. 所以每个子层是瓦片数量的 9 倍(第一层 12 个,第二层 108 个,第三层 972 个)

  6. 每个图块都有一个背景图像(大小约为 6KB)(从服务器加载为图像)和前景信息(从服务器为每个图块加载为 JSON - 大小为 10-15KB)
    -> 前景信息 JSON 包含叠加图像(例如 google 中的流量)或要绘制到本地图块坐标空间中的本地图块信息(如注释,但每个图块)

  7. 我想在磁盘上缓存整个背景图块,因为它们永远不会改变

  8. 要么我想缓存每个图块的覆盖图块图像/覆盖图块信息一段时间,直到它应该再次重新加载

  9. 缩放应该是捏合和双击

我的一些考虑:

  1. 缓存不是问题。我是通过 CoreData 或类似的

  2. 我想到了一个 UIScrollView,以显示平滑滚动

  3. 我想使用捏合,所以每次突破下一个缩放级别时,我都必须绘制下一个缩放级别的图块

  4. 内容应该只绘制在可见区域(对于我在 iPhone 5 320x500 上)

  5. 不可见的瓷砖应该被删除,以节省内存。但它们不应该立即被删除,只有当瓦片远离可见中心一定数量的像素/点时。应该有一个“显示缓存”,以即时显示刚刚加载和显示的图块。或者那里有更好的技术?

  6. 我可以立即从磁盘或服务器异步加载背景,因为我知道哪些图块是可见的。我对 tile-JSON 也是如此。然后我提取图块的 JSON 信息(“叠加层是直接图像还是诸如城市名称之类的信息,我必须将其绘制到图块中”)并绘制或加载叠加层(来自 DB/Disc 或服务器)

  7. UIScrollView 是否足够高效以处理平铺视图的最大尺寸

  8. 我应该使用 CALayer 作为子图层来绘制它吗?我应该使用 Quartz 直接在大“画布”上绘制吗?

现在轮到你了 !!!

4

3 回答 3

4

Apple 有一个示例,显示将单个图像放大到非常深。他们为此使用了 CATiledLayer。

该示例可以在这里找到:http: //developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html

该示例适用于存储在手机上的子图块,但也许它可以适应您的问题。

于 2013-02-22T09:55:42.687 回答
2

我想出了一个非常简洁和好的解决方案(自定义 TiledLayer 实现):

我不再使用 CATiledLayer 作为 scrollView 的 contentView 了。相反,我向它添加了一个 CALayer 子类,并将我的图块作为子层添加到它。每个图块都包含图块位图作为内容。使用滚动视图放大时,我会根据当前缩放级别手动切换图块。那很完美!!!

如果有人想知道实现的细节 -> 没问题,写评论,我把它贴在这里。


编辑

有关实施的详细信息:

实际上实现非常简单:

  1. 将 UIScrollView 添加到您的视图/控制器视图
  2. 将 UIView(从现在称为tileView)作为 contentView 添加到 ScrollView - 与 ScrollView 大小相同(这是完全缩小模式 - 因子 1)
  3. 激活缩放(我的最小缩放因子为 1,最大为 9)
  4. 当您现在将图像放入 中时tileView,放大到第 9 级将给出非常不清晰的像素化图像 - 这就是我们想要的(我将解释原因)
  5. 如果您在放大时喜欢清晰的图像,您应该添加 CALayer 实例 ( tiles)addSublayer:tileView
  6. 假设您的 zoomFactor 为 3(我有 - 意思是第 0 层中的 1 个平铺 - zoomFactor 1将由第 1 层中的3x3 = 9 个平铺- zoomFactor 3 组成
    1. 第 0 层中,假设您放置了 3x4 243x243(3 倍可除以 3)像素的图块(作为 的子层tileView)。您将相同大小的平铺图像放置为CALayer contents. 缩放到zoomFactor 3会使它们变得模糊(就像旧的谷歌地图)
    2. 当您点击zoomFactor 3时,从 superlayer 中删除所有 12 层,并将它们替换为小 3 倍(81x81 像素)的层。你得到的层数是整体的 9 倍。
    3. 现在您有 3 倍的小图块层,诀窍.contentsCALayer. 即使图层是 81x81,内容(您的图像)仍然是全分辨率,这意味着如果您将 243x243 像素图像作为 81x81 像素 CALayer 瓦片的内容,在zoomFactor 3上 它看起来像一个 243x243 像素瓦片!!!

您可以在更深的任何 zoomFactor (3,9,12) 上使用它。瓷砖变得越来越小,但是将原始图像设置为内容,瓷砖将在它们放置的确切缩放因子下看起来清晰锐利。

如果您希望即使在 zoomFactors 之间您的图块看起来也很清晰,则必须将 3 倍高的图像设置为.contents. 然后,在您通过下一个 zoomLevel 之前,您的图块即使很短也清晰锐利。

您必须弄清楚的一件事是,通过 zoomLevel 因子时删除图层上的所有图块效率不高您只需更新 rect 中的可见图块。

不是所有解决方案中最好的,但它可以工作,如果有人做了一个设计良好的库,也许这有可能成为一个干净的解决方案。

于 2013-02-26T16:36:30.993 回答
2

我已经使用我自己的 TiledLayer 实现来解决 CATiledLayer 不支持的这些类型的非标准平铺问题(并且因为 CATiledLayer 仍然有一些未解决的错误)。

该实现现在在Github上可用。

Fab1n:这与我已经通过电子邮件发送给您的实现相同。

于 2013-03-01T15:23:38.563 回答