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