SwiftUI で SVG Based Maps をインタラクティブに使用するためのライブラリ。
Shape
提供する属性を使用して、マップ内のすべての州を変更できます。注記! SVG 解析はまだ最終形式ではないため、一部の SVG は正しく解析されない可能性があります。しかし、私が見る限り、ほぼすべての地図は正しく描画されています。私が試したマップは「マップ」セクションでご覧いただけます。
マップは FSInteractiveMap リポジトリから取得されます
iOS 13以降が必要です
InteractiveMap は現在、Swift Package Manager を通じてのみインストールできます。
Swiftパッケージマネージャー パッケージの URL を追加します。 |
|
3D スケーリング効果
不気味な地図
ミマンダル州選択画面
SwiftUI で SVG マップを描画するには、 PathData
パラメータとして受け取るクロージャーを含むInteractiveMap
使用します。
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 を比較します。
すぐ
すぐ