美文网首页iOS地图
MapKit框架详细解析(七) —— 添加自定义图块(二)

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

作者: 刀客传奇 | 来源:发表于2019-04-25 19:03 被阅读4次

    版本记录

    版本号 时间
    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显示了中央公园的底部。该应用程序包含许多这些小图像,以形成游戏发生的纽约市地图,每个图像都是使用漂亮的基本技能和工具手工绘制的。

    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)路径将显示在控制台输出中。

    接下来是获取源图块然后自定义它的问题。 您可以重复使用之前的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
    

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

    2. Customizing Appearances

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

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

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

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

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

    • 首先将整个图层的所有图块组合在一起。
    • 绘制自定义地图。
    • 将地图拆分回图块。

    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非常灵活,但它只用于代表冒险者只有一个图像。

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

    2. Annotations for Specific Locations

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

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

    mapView.addAnnotations(Game.shared.warps)
    

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

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

    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
    

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


    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
      }
    }
    

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

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

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

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

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

    后记

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

    相关文章

      网友评论

        本文标题:MapKit框架详细解析(七) —— 添加自定义图块(二)

        本文链接:https://www.haomeiwen.com/subject/rjvzgqtx.html