在 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。
很快
很快