MapKit框架详细解析(七) —— 添加自定义图块(二)

版本记录

版本号 时间
V1.0 2019.04.25 星期四

前言

MapKit框架直接从您的应用界面显示地图或卫星图像,调出兴趣点,并确定地图坐标的地标信息。接下来几篇我们就一起看一下这个框架。感兴趣的看下面几篇文章。
1. MapKit框架详细解析(一) —— 基本概览(一)
2. MapKit框架详细解析(二) —— 基本使用简单示例(一)
3. MapKit框架详细解析(三) —— 基本使用简单示例(二)
4. MapKit框架详细解析(四) —— 一个叠加视图相关的简单示例(一)
5. MapKit框架详细解析(五) —— 一个叠加视图相关的简单示例(二)
6. MapKit框架详细解析(六) —— 添加自定义图块(一)

Creating Tiles

下一部分是可选的,因为它涵盖了如何绘制特定的图块。 要跳到更多MapKit技术,请跳到Fancifying the Map部分。

整个过程中最难的部分是制作合适尺寸的图块并正确排列。 要绘制自己的自定义图块,您需要一个数据源和一个图像编辑器。

打开项目文件夹,看看MapQuest / tiles / 14/4885 / 6156.png。 这个图块在缩放级别14显示了中央公园的底部。该应用程序包含许多这些小图像,以形成游戏发生的纽约市地图,每个图像都是使用漂亮的基本技能和工具手工绘制的。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第1张图片

1. What Tiles Do You Need?

第一步是弄清楚你需要绘制哪些图块。 您可以从Open Street Map下载源数据,并使用 MapNik等工具从中生成图块图像。 不幸的是,源代码是57GB下载! 这些工具有点模糊,超出了本教程的范围。

对于像中央公园这样的有界区域,有一个更容易的解决方法。

AdventureMapOverlay.swift中,将以下行添加到url(forTilePath :)

print("requested tile\tz:\(path.z)\tx:\(path.x)\ty:\(path.y)")

建立并运行。 现在,当您在地图上缩放和平移时,图块(tile)路径将显示在控制台输出中。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第2张图片

接下来是获取源图块然后自定义它的问题。 您可以重复使用之前的URL方案来获取打开的街道地图图块。

以下终端命令将在本地获取并存储它。 您可以更改URL,将x,y和z替换为特定的地图路径。

curl --create-dirs -o z/x/y.png https://tile.openstreetmap.org/z/x/y.png

在中央公园的南部,尝试:

curl --create-dirs -o 14/4825/6156.png https://tile.openstreetmap.org/14/4825/6156.png
MapKit框架详细解析(七) —— 添加自定义图块(二)_第3张图片

zoom-level/x-coordinate/y-coordinate的目录结构使以后更容易查找和使用图块。

2. Customizing Appearances

下一步是使用基本图像作为自定义的起点。 在您喜欢的图像编辑器中打开图块。 例如,这就是Pixelmator的样子:

MapKit框架详细解析(七) —— 添加自定义图块(二)_第4张图片

现在,您可以使用画笔或铅笔工具绘制道路,路径或有趣的特征。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第5张图片

如果您的工具支持图层,则在不同图层上绘制不同的要素将允许您调整它们以获得最佳外观。 使用图层可以使绘图更加宽容,因为您可以掩盖其他特征下方的杂乱线条。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第6张图片
MapKit框架详细解析(七) —— 添加自定义图块(二)_第7张图片

现在对集合中的所有图块重复此过程,您就可以开始了。 如您所见,这将是一点点时间投资。

您可以使过程更容易一些:

  • 首先将整个图层的所有图块组合在一起。
  • 绘制自定义地图。
  • 将地图拆分回图块。
MapKit框架详细解析(七) —— 添加自定义图块(二)_第8张图片

3. Where to Put the Tiles

创建新图块后,将它们放回项目中的tiles/zoom-level/x-coordinate/y-coordinate文件夹结构中。 这使得事情井井有条,易于访问。

这意味着您可以轻松访问它们,就像您为url(forTilePath :)添加的代码中所做的那样。

let tilePath = Bundle.main.url(
    forResource: "\(path.y)",
    withExtension: "png",
    subdirectory: "tiles/\(path.z)/\(path.x)",
    localization: nil)

就这些,现在你准备出去画一些漂亮的地图吧!


Fancifying the Map

地图看起来很棒,适合游戏的美学。 但是还有更多的定制!

您的英雄没有很好地用蓝点表示,但您可以用一些自定义艺术替换当前位置注释。

1. The User Annotation

打开MapViewController.swift并将以下方法添加到MapView Delegate扩展:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  switch annotation {
    
  // 1
  case let user as MKUserLocation:
    
    // 2
    let view = mapView.dequeueReusableAnnotationView(withIdentifier: "user")
      ?? MKAnnotationView(annotation: user, reuseIdentifier: "user")
    
    // 3
    view.image = #imageLiteral(resourceName: "user")
    return view
    
  default:
    return nil
  }
}

此代码为用户注释创建自定义视图。

  • 1) 用户的位置使用MKUserLocation进行注释。
  • 2) MapViews维护一组可重用的注释视图,以提高性能。 如果没有出列,这将创建一个新的。
  • 3) 标准的MKAnnotationView非常灵活,但它只用于代表冒险者只有一个图像。

建立并运行。 而不是蓝点,现在会有一个小棒图徘徊。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第9张图片

2. Annotations for Specific Locations

MKMapView还允许您标记自己感兴趣的位置。 MapQuest与纽约地铁一起运行,将地铁系统视为一个伟大的大型经线网络。

在地图上为附近的地铁站添加一些标记。 打开MapViewController.swift,在viewDidLoad()的末尾添加以下行:

mapView.addAnnotations(Game.shared.warps)

构建和运行,一系列地铁站现在表示为引脚pins

MapKit框架详细解析(七) —— 添加自定义图块(二)_第10张图片

与用户位置蓝点一样,这些标准针脚与游戏的美学并不完全匹配。 自定义注释可以解决问题。

mapView(_:viewFor :)中,将以下case写添加到default case上方的switch语句中:

case let warp as WarpZone:
  let view = mapView.dequeueReusableAnnotationView(withIdentifier: WarpAnnotationView.identifier)
    ?? WarpAnnotationView(annotation: warp, reuseIdentifier: WarpAnnotationView.identifier)
  view.annotation = warp
  return view

构建并再次运行。 自定义注释视图将使用模板图像并为特定地铁线路着色。

MapKit框架详细解析(七) —— 添加自定义图块(二)_第11张图片

Custom Overlay Rendering

MapKit有很多方法可以为游戏修饰地图。 接下来,使用MKPolygonRenderer在储层上绘制基于梯度的微光效果。

setupLakeOverlay()替换为:

func setupLakeOverlay() {

 // 1
 let lake = MKPolygon(coordinates: &Game.shared.reservoir, count: Game.shared.reservoir.count)
 mapView.add(lake)

 // 2
 shimmerRenderer = ShimmerRenderer(overlay: lake)
 shimmerRenderer.fillColor = #colorLiteral(red: 0.2431372549, green: 0.5803921569, blue: 0.9764705882, alpha: 1)

 // 3
 Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
   self?.shimmerRenderer.updateLocations()
   self?.shimmerRenderer.setNeedsDisplay()
 }
}

这将通过以下方式设置新的叠加层:

  • 1) 创建与储层形状相同的MKPolygon注释。 这些坐标在Game.swift中预编程。
  • 2) 设置自定义渲染器以使用特殊效果绘制多边形。
  • 3) 由于叠加渲染器不是动画,因此设置100ms计时器来更新叠加层。

接下来,将mapView(_:rendererFor :)替换为:

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
  if overlay is AdventureMapOverlay {
    return tileRenderer
  } else {
    return shimmerRenderer
  }
}

这将为两个叠加中的每一个选择正确的渲染器。

再次构建并运行。 然后平移到水库,看到闪闪发光的海!

MapKit框架详细解析(七) —— 添加自定义图块(二)_第12张图片

创建手绘地图图块非常耗时,但使用它们可以为应用程序提供独特且身临其境的感觉。 除了创建资源之外,使用它们非常简单。

除了基本图块之外,Open Street Map还有一个specialized tile providers列表,用于骑自行车和地形等。 如果您想以编程方式设计自己的图块,Open Street Map还会提供您可以使用的数据。

如果您想要一个自定义但逼真的地图外观,而无需手工绘制所有内容,请查看第三方工具,例如MapBox。 它允许您以适中的价格使用优质工具自定义地图的外观。

后记

本篇主要介绍了添加自定义图块,感兴趣的给个赞或者关注~~~

你可能感兴趣的:(MapKit框架详细解析(七) —— 添加自定义图块(二))