高效的自定义平铺地图,具有自定义缩放级别和缩放系数

时间:2013-02-22 08:45:43

标签: ios uiscrollview maps catiledlayer

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

  1. 谷歌地图
  2. route-me (由MapBox使用)
  3. CATiledLayerUIScrollView
  4. 组合使用

    事情是:由于我的具体规格,所有解决方案都没有真正帮助我。如果你认为,有一个合适的解决方案,请告诉我!!!

    如果不是:
    帮助我为我的案例寻找最佳解决方案!!!

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

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

    2. 每个图块在下一个缩放级别(=缩放系数 3 )中有个9个子图标(与大多数其他套件不同 4 subtiles = zoomfactor 2

    3. 第一层的初始大小为(以像素为单位,以点为单位)为768 * 1024。 第二层宽三倍( zoomfactor 3 !!! ) - > 2304 * 3072
      第三层同样宽且高于第二层 - > 6912 * 9216

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

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

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

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

    8. 我想在一段时间内为每个图块缓存overlay-tile-images / overlay-tile-information,直到它再次重新加载

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

    10. 我的一些注意事项:

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

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

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

      5. 内容应仅在可见区域绘制(对我来说,在iPhone 5 320x500上)

      6. 应删除不可见的切片,以提高内存效率。但是,不应该立即删除它们,只有当一块瓷砖远离可见中心的一定像素/点时才会被删除。应该有一个“显示缓存”,即时显示瓷砖,只是加载和显示。或者那里有更好的技术吗?

      7. 我可以异步地从磁盘或服务器加载背景,因为我知道哪些图块是可见的。我也是使用tile-JSON。然后我提取瓷砖的JSON信息(“是覆盖直接图像或信息,如城市名称,我必须绘制到瓷砖”)并绘制或加载覆盖(来自DB / Disc或Server)

      8. UIScrollView是否足以处理磁贴视图的最大大小

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

      10. 现在轮到你了!!!

3 个答案:

答案 0 :(得分:4)

Apple有一个示例,可以显示非常深的单个图像。他们使用CATiledLayer。

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

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

答案 1 :(得分: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. 假设你有一个3的zoomFactor(我有 - 在第0层中意味着1个平铺 - zoomFactor 1 将包含第1层中的 3x3 = 9个平铺 - zoomFactor 3
    1. 第0层中,假设您将3x4图块放入243x243(3次可偏离3次)像素(作为tileView的子图层)。您将相同尺寸的图块图像设为CALayer contents。缩放到 zoomFactor 3 使它们变得模糊(就像旧谷歌地图一样)
    2. 当您点击 zoomFactor 3 时,从超级图层中删除所有12个图层,并将其替换为3次较小的图层( 81x81像素)。你得到的图层总数是你的9倍。
    3. 现在您的图块层数减少了3倍,诀窍是.contents的{​​{1}}属性。即使图层为81x81,内容(您的图像)仍然是仍然是全分辨率,这意味着如果您将<34>像素CALayer图块的243x243像素图像放在 zoomFactor 3上 它看起来像一块243x243像素的瓷砖!!!
  7. 你可以更深入地使用任何zoomFactor(3,9,12)。瓷砖越来越小,但将原始图像设置为内容,瓷砖在放置它们的精确zoomFactor上看起来会变得清晰锐利。

    如果你喜欢你的瓷砖在zoomFactors之间看起来很清晰,你必须设置一个高3倍的图像CALayer。然后,在你通过下一个zoomLevel之前,你的瓷砖就会变得清脆锐利。

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

    不是所有解决方案中最好的解决方案,但它有效,如果有人设计精良的图书馆,也许有可能成为一个干净的解决方案。

答案 2 :(得分:2)

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

该实施现已在Github上提供。

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