在 SwiftUI 中交互使用基于 SVG 的地图的库。
Shape
提供的属性修改地图中的所有省份笔记! SVG 解析尚未达到最终形式,因此某些 SVG 可能无法正确解析。但据我所知,几乎每张地图都绘制正确。您可以在“地图”部分查看我尝试过的地图。
地图取自 FSInteractiveMap Repository
需要iOS 13+
InteractiveMap 目前只能通过 Swift Package Manager 安装。
斯威夫特包管理器 添加包 URL: |
|
3D缩放效果
令人毛骨悚然的地图
米赫曼达尔省选择屏幕
要在 SwiftUI 中绘制 svg 地图,请使用InteractiveMap
和以PathData
作为参数的闭包。
InteractiveMap
使用InteractiveShape
来绘制 SVG 中定义的所有路径。但它需要知道将绘制哪条Path
,即InteractiveMap { pathData in }
的工作方式与ForEach { index in }
类似,并返回一个可迭代闭包,该闭包返回PathData
作为参数,其中包含有关 svg 中定义的Path
的所有信息。
import SwiftUI
import InteractiveMap
struct ContentView : View {
var body : some View {
InteractiveMap ( svgName : " tr " ) { pathData in // or just use $0
InteractiveShape ( pathData )
. initWithAttributes ( )
}
}
}
InteractiveMap 会根据指定的帧调整自身大小,默认情况下占用所有可用空间,并根据设备旋转响应调整自身大小。
您也可以定义自己的属性,而不是使用默认属性。
InteractiveMap ( svgName : " tr " ) {
InteractiveShape ( $0 )
. initWithAttributes ( . init ( strokeWidth : 2 , strokeColor : . red , background : Color ( white : 0.2 ) ) )
}
尽管.initWithAttributes
可以节省简单定制的时间,但它既不是高度可定制的,也不是可编辑的。
由于InteractiveShape
是一个Shape
,因此您可以将任何可以与Shape
一起使用的方法与InteractiveShape
一起使用。
InteractiveMap ( svgName : " tr " ) {
InteractiveShape ( $0 )
. stroke ( Color . cyan )
. shadow ( color : . cyan , radius : 3 , x : 0 , y : 0 )
. background ( InteractiveShape ( $0 ) . fill ( Color ( white : 0.15 ) ) )
}
PathData
是一个Struct
,包含所有路径的所有信息,在我们的地图示例中,它们是地区和省份。
它里面有5个变量。 id
、 path
和name
、 boundingBox
和svgBounds
id
是直接从 SVG 解析的唯一标识符
大多数 Map SVG(不是全部!)在其<path>
元素中都有id
属性,如下所示:
<path ... id="<id>", name="<name>">
在MapParser.swift
中定义的MapParser
解析该元素并将它们存储在PathData
结构中。
如果路径中没有任何id
属性,MapParser 会自动创建一个 UUID 字符串。
但如果您打算将该 id 存储在某个地方,请注意每次绘制 InteractiveMap 时都会自动重新生成 UUID 字符串。
import SwiftUI
import InteractiveMap
struct ContentView : View {
@ State private var clickedPath = PathData ( )
var body : some View {
VStack {
Text ( clickedPath . name . isEmpty ? " " : " ( clickedPath . name ) is clicked! " )
. font ( . largeTitle )
. padding ( . bottom , 15 )
InteractiveMap ( svgName : " tr " ) { pathData in // is a PathData
InteractiveShape ( pathData )
. stroke ( clickedPath == pathData ? . cyan : . red , lineWidth : 1 )
. shadow ( color : clickedPath == pathData ? . cyan : . red , radius : 3 )
. shadow ( color : clickedPath == pathData ? . cyan : . clear , radius : 3 ) // to increase the glow amount
. background ( InteractiveShape ( pathData ) . fill ( Color ( white : 0.15 ) ) ) // filling the shapes
. shadow ( color : clickedPath == pathData ? . black : . clear , radius : 5 , y : 1 ) // for depth
. onTapGesture {
clickedPath = pathData
}
. zIndex ( clickedPath == pathData ? 2 : 1 ) // this is REQUIRED because InteractiveShapes overlap, resulting in an ugly appearance
. animation ( . easeInOut ( duration : 0.3 ) , value : clickedPath )
}
}
}
}
clickedPath == pathData
基本上比较 PathData 的 id。
很快
很快