@@ -5,13 +5,23 @@ import MapLibreSwiftMacros
5
5
6
6
@MLNStyleProperty < Double > ( " iconRotation " , supportsInterpolation: true )
7
7
@MLNStyleProperty < UIColor > ( " iconColor " , supportsInterpolation: true )
8
+ @MLNStyleProperty < Bool > ( " iconAllowsOverlap " , supportsInterpolation: false )
9
+
8
10
@MLNStyleProperty < UIColor > ( " textColor " , supportsInterpolation: true )
9
11
@MLNStyleProperty < Double > ( " textFontSize " , supportsInterpolation: true )
10
12
@MLNStyleProperty < String > ( " text " , supportsInterpolation: false )
11
- @MLNStyleProperty < Bool > ( " iconAllowsOverlap " , supportsInterpolation: false )
13
+ // An enum would probably be better?
14
+ @MLNStyleProperty < String > ( " textAnchor " , supportsInterpolation: false )
15
+ @MLNStyleProperty < CGVector > ( " textOffset " , supportsInterpolation: true )
16
+ @MLNStyleProperty < Double > ( " maximumTextWidth " , supportsInterpolation: true )
17
+
18
+ @MLNStyleProperty < UIColor > ( " textHaloColor " , supportsInterpolation: true )
19
+ @MLNStyleProperty < Double > ( " textHaloWidth " , supportsInterpolation: true )
20
+ @MLNStyleProperty < Double > ( " textHaloBlur " , supportsInterpolation: true )
12
21
13
22
public struct SymbolStyleLayer : SourceBoundVectorStyleLayerDefinition {
14
23
public let identifier : String
24
+ public let sourceLayerIdentifier : String ?
15
25
public var insertionPosition : LayerInsertionPosition = . aboveOthers
16
26
public var isVisible : Bool = true
17
27
public var maximumZoomLevel : Float ? = nil
@@ -22,11 +32,13 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition {
22
32
23
33
public init ( identifier: String , source: Source ) {
24
34
self . identifier = identifier
35
+ sourceLayerIdentifier = nil
25
36
self . source = . source( source)
26
37
}
27
38
28
- public init ( identifier: String , source: MLNSource ) {
39
+ public init ( identifier: String , source: MLNSource , sourceLayerIdentifier : String ? = nil ) {
29
40
self . identifier = identifier
41
+ self . sourceLayerIdentifier = sourceLayerIdentifier
30
42
self . source = . mglSource( source)
31
43
}
32
44
@@ -40,10 +52,9 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition {
40
52
return SymbolStyleLayerInternal ( definition: self , mglSource: styleSource)
41
53
}
42
54
43
- // TODO: Other properties and their modifiers
44
- fileprivate var iconImageName : NSExpression ?
55
+ public var iconImageName : NSExpression ?
45
56
46
- private var iconImages = [ UIImage] ( )
57
+ public var iconImages = [ UIImage] ( )
47
58
48
59
// MARK: - Modifiers
49
60
@@ -54,18 +65,42 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition {
54
65
}
55
66
}
56
67
57
- // FIXME: This appears to be broken upstream; waiting for a new release
58
- // public func iconImage(attribute: String, mappings: [AnyHashable: UIImage], default defaultImage: UIImage) -> Self
59
- // {
60
- // return modified(self) { it in
61
- // it.iconImageName = NSExpression(forMLNMatchingKey: NSExpression(forConstantValue: attribute),
62
- // in: Dictionary(uniqueKeysWithValues: mappings.map({ (k, v) in
63
- // (NSExpression(forConstantValue: k), NSExpression(forConstantValue: v.sha256()))
64
- // })),
65
- // default: NSExpression(forConstantValue: defaultImage.sha256()))
66
- // it.iconImages = mappings.values + [defaultImage]
67
- // }
68
- // }
68
+ public func iconImage( featurePropertyNamed keyPath: String ) -> Self {
69
+ var copy = self
70
+ copy. iconImageName = NSExpression ( forKeyPath: keyPath)
71
+ return copy
72
+ }
73
+
74
+ /// Add an icon image that can be dynamic and use UIImages in your app, based on a feature property of the source.
75
+ /// For example, your feature could have a property called "icon-name". This name is then resolved against the key
76
+ /// in the mappings dictionary and used to find a UIImage to display on the map for that feature.
77
+ /// - Parameters:
78
+ /// - keyPath: The keypath to the feature property containing the icon to use, for example "icon-name".
79
+ /// - mappings: A lookup dictionary containing the keys found in "keyPath" and a UIImage for each keyPath. The key
80
+ /// of the mappings dictionary needs to match the value type stored at keyPath, for example `String`.
81
+ /// - defaultImage: A UIImage that MapLibre should fall back to if the key in your feature is not found in the
82
+ /// mappings table
83
+ public func iconImage(
84
+ featurePropertyNamed keyPath: String ,
85
+ mappings: [ AnyHashable : UIImage ] ,
86
+ default defaultImage: UIImage
87
+ ) -> Self {
88
+ modified ( self ) { it in
89
+ let attributeExpression = NSExpression ( forKeyPath: keyPath)
90
+ let mappingExpressions = mappings. mapValues { image in
91
+ NSExpression ( forConstantValue: image. sha256 ( ) )
92
+ }
93
+ let mappingDictionary = NSDictionary ( dictionary: mappingExpressions)
94
+ let defaultExpression = NSExpression ( forConstantValue: defaultImage. sha256 ( ) )
95
+
96
+ it. iconImageName = NSExpression (
97
+ forMLNMatchingKey: attributeExpression,
98
+ in: mappingDictionary as! [ NSExpression : NSExpression ] ,
99
+ default: defaultExpression
100
+ )
101
+ it. iconImages = mappings. values + [ defaultImage]
102
+ }
103
+ }
69
104
}
70
105
71
106
private struct SymbolStyleLayerInternal : StyleLayer {
@@ -100,18 +135,34 @@ private struct SymbolStyleLayerInternal: StyleLayer {
100
135
101
136
public func makeMLNStyleLayer( ) -> MLNStyleLayer {
102
137
let result = MLNSymbolStyleLayer ( identifier: identifier, source: mglSource)
138
+ result. sourceLayerIdentifier = definition. sourceLayerIdentifier
103
139
104
140
result. iconImageName = definition. iconImageName
105
141
result. iconRotation = definition. iconRotation
142
+ result. iconAllowsOverlap = definition. iconAllowsOverlap
106
143
result. iconColor = definition. iconColor
144
+
107
145
result. text = definition. text
108
146
result. textColor = definition. textColor
109
147
result. textFontSize = definition. textFontSize
148
+ result. maximumTextWidth = definition. maximumTextWidth
149
+ result. textAnchor = definition. textAnchor
150
+ result. textOffset = definition. textOffset
110
151
111
- result. iconAllowsOverlap = definition. iconAllowsOverlap
152
+ result. textHaloColor = definition. textHaloColor
153
+ result. textHaloWidth = definition. textHaloWidth
154
+ result. textHaloBlur = definition. textHaloBlur
112
155
113
156
result. predicate = definition. predicate
114
157
158
+ if let minimumZoomLevel = definition. minimumZoomLevel {
159
+ result. minimumZoomLevel = minimumZoomLevel
160
+ }
161
+
162
+ if let maximumZoomLevel = definition. maximumZoomLevel {
163
+ result. maximumZoomLevel = maximumZoomLevel
164
+ }
165
+
115
166
return result
116
167
}
117
168
}
0 commit comments