@@ -17,21 +17,24 @@ import SwiftUI
17
17
/// A `Compass` (alias North arrow) shows where north is in a `MapView` or
18
18
/// `SceneView`.
19
19
public struct Compass : View {
20
- /// A Boolean value indicating whether the compass should automatically
21
- /// hide/show itself when the heading is `0`.
22
- private let autoHide : Bool
23
-
24
20
/// The opacity of the compass.
25
21
@State private var opacity : Double = . zero
26
22
23
+ /// An action to perform when the compass is tapped.
24
+ private let action : ( ( ) -> Void ) ?
25
+
26
+ /// A Boolean value indicating whether the compass should automatically
27
+ /// hide/show itself when the heading is `0`.
28
+ private var autoHide : Bool = true
29
+
27
30
/// A Boolean value indicating whether the compass should hide based on the
28
31
/// current heading and whether the compass automatically hides.
29
32
var shouldHide : Bool {
30
33
( heading. isZero || heading. isNaN) && autoHide
31
34
}
32
35
33
36
/// The width and height of the compass.
34
- var size : CGFloat = 44
37
+ private var size : CGFloat = 44
35
38
36
39
/// The heading of the compass in degrees.
37
40
@Binding private var heading : Double
@@ -41,14 +44,13 @@ public struct Compass: View {
41
44
/// direction toward true East, etc.).
42
45
/// - Parameters:
43
46
/// - heading: The heading of the compass.
44
- /// - autoHide: A Boolean value that determines whether the compass
45
- /// automatically hides itself when the heading is `0`.
47
+ /// - action: An action to perform when the compass is tapped.
46
48
public init (
47
49
heading: Binding < Double > ,
48
- autoHide : Bool = true
50
+ action : ( ( ) -> Void ) ? = nil
49
51
) {
50
52
_heading = heading
51
- self . autoHide = autoHide
53
+ self . action = action
52
54
}
53
55
54
56
public var body : some View {
@@ -60,16 +62,22 @@ public struct Compass: View {
60
62
}
61
63
. aspectRatio ( 1 , contentMode: . fit)
62
64
. opacity ( opacity)
63
- . onTapGesture { heading = . zero }
64
65
. frame ( width: size, height: size)
66
+ . onAppear { opacity = shouldHide ? 0 : 1 }
65
67
. onChange ( of: heading) { _ in
66
68
let newOpacity : Double = shouldHide ? . zero : 1
67
69
guard opacity != newOpacity else { return }
68
70
withAnimation ( . default. delay ( shouldHide ? 0.25 : 0 ) ) {
69
71
opacity = newOpacity
70
72
}
71
73
}
72
- . onAppear { opacity = shouldHide ? 0 : 1 }
74
+ . onTapGesture {
75
+ if let action {
76
+ action ( )
77
+ } else {
78
+ heading = . zero
79
+ }
80
+ }
73
81
. accessibilityLabel ( " Compass, heading \( Int ( heading. rounded ( ) ) ) degrees \( CompassDirection ( heading) . rawValue) " )
74
82
}
75
83
}
@@ -82,28 +90,27 @@ public extension Compass {
82
90
/// - Parameters:
83
91
/// - viewpointRotation: The viewpoint rotation whose value determines the
84
92
/// heading of the compass.
85
- /// - autoHide: A Boolean value that determines whether the compass
86
- /// automatically hides itself when the viewpoint rotation is 0 degrees.
93
+ /// - action: An action to perform when the compass is tapped.
87
94
init (
88
95
viewpointRotation: Binding < Double > ,
89
- autoHide : Bool = true
96
+ action : ( ( ) -> Void ) ? = nil
90
97
) {
91
98
let heading = Binding ( get: {
92
99
viewpointRotation. wrappedValue. isZero ? . zero : 360 - viewpointRotation. wrappedValue
93
100
} , set: { newHeading in
94
101
viewpointRotation. wrappedValue = newHeading. isZero ? . zero : 360 - newHeading
95
102
} )
96
- self . init ( heading: heading, autoHide : autoHide )
103
+ self . init ( heading: heading, action : action )
97
104
}
98
105
99
106
/// Creates a compass with a binding to an optional viewpoint.
100
107
/// - Parameters:
101
108
/// - viewpoint: The viewpoint whose rotation determines the heading of the compass.
102
- /// - autoHide: A Boolean value that determines whether the compass automatically hides itself
109
+ /// - action: An action to perform when the compass is tapped.
103
110
/// when the viewpoint's rotation is 0 degrees.
104
111
init (
105
112
viewpoint: Binding < Viewpoint ? > ,
106
- autoHide : Bool = true
113
+ action : ( ( ) -> Void ) ? = nil
107
114
) {
108
115
let viewpointRotation = Binding {
109
116
viewpoint. wrappedValue? . rotation ?? . nan
@@ -115,7 +122,7 @@ public extension Compass {
115
122
rotation: newViewpointRotation
116
123
)
117
124
}
118
- self . init ( viewpointRotation: viewpointRotation, autoHide : autoHide )
125
+ self . init ( viewpointRotation: viewpointRotation, action : action )
119
126
}
120
127
121
128
/// Define a custom size for the compass.
@@ -125,4 +132,13 @@ public extension Compass {
125
132
copy. size = size
126
133
return copy
127
134
}
135
+
136
+ /// Specifies whether the ``Compass`` should automatically hide when the heading is 0.
137
+ /// - Parameter flag: A Boolean value indicating whether the compass should automatically
138
+ /// hide/show itself when the heading is `0`.
139
+ func automaticallyHides( _ flag: Bool ) -> some View {
140
+ var copy = self
141
+ copy. autoHide = flag
142
+ return copy
143
+ }
128
144
}
0 commit comments