【问题标题】:Efficient custom tiled maps with custom zoom levels and zoom factors具有自定义缩放级别和缩放系数的高效自定义平铺地图
【发布时间】:2013-02-07 19:51:28
【问题描述】:

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

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

问题是:由于我的具体规格,没有任何解决方案能真正帮助我。如果你觉得有合适的解决方案,请告诉我!!!

如果不是:
帮我找到适合我的情况的最佳解决方案!!!

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

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

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

  3. 第一层的初始大小为 768*1024。
    第二层是三倍宽和高(zoomfactor 3!!!)-> 2304*3072
    第三层同样比第二层更宽更高 -> 6912*9216

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

  5. 所以每个子层是瓦片数量的 9 倍(第 1 层 12 个,第 2 层 108 个,第 3 层 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 信息(“是覆盖直接图像或诸如城市名称之类的信息,我必须将其绘制到图块中”)并绘制或加载覆盖(从数据库/光盘或服务器)

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

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

现在轮到你了!!!

【问题讨论】:

  • 不能投票结束,因为这个问题有赏金,但这个问题太宽泛了。你应该问具体的事情,而不是列出十几个要求。

标签: ios uiscrollview maps catiledlayer


【解决方案1】:

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

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

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

【讨论】:

  • CATiledLayer 会非常完美。但我们的缩放系数为 3,而不是 2,就像在几乎所有地图视图和 CATiledLayer 中一样
【解决方案2】:

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

该实现现已在 Github 上提供。

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

【讨论】:

  • 非常感谢。我意识到,我的项目是专门使用你的,但做得很好。其他的都用完了……
  • 因为我不能给任何人赏金,你会得到它,因为你的大力支持,你给我看。你应得的。
【解决方案3】:

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

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

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


编辑

实现细节:

其实实现真的很简单:

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

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

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

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

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

【讨论】:

  • 你说的是我的实现,还是你自己推出的?
  • @Fab1n,嘿伙计,是的,我很高兴知道您的实施的具体细节。我会很高兴你发布它。谢谢 Fab1n,期待您的回复!
  • @Pavan 2 个月后您的回复......对不起,我现在很忙,当时也不太活跃。你认识的家人 :-) 当我能够提供有关实施的详细信息时,我真的无法告诉你。对此感到抱歉
  • @Fab1n 就在我希望你能不辜负你在帖子中写的内容时:P。嘿,没问题,我知道你很忙,我也很忙,因为我排了所有这些项目,我发现如果我在上厕所休息时随身携带笔记本电脑,我有一个额外5分钟!请利用这段时间制作一个 git 存储库或类似的东西来上传项目?我会很感激。谢谢
  • @Pavan 我不会对此做出承诺,但至少我会尝试 :-)
猜你喜欢
  • 2018-10-07
  • 2017-10-14
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
  • 2013-05-14
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
相关资源
最近更新 更多