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
显示了中央公园的底部。该应用程序包含许多这些小图像,以形成游戏发生的纽约市地图,每个图像都是使用漂亮的基本技能和工具手工绘制的。
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。 它允许您以适中的价格使用优质工具自定义地图的外观。
后记
本篇主要介绍了添加自定义图块,感兴趣的给个赞或者关注~~~