Skip to content

Commit dd2cdc5

Browse files
OdNairygithub-actions[bot]
authored andcommitted
[maps-ios] Elevated line example
Implements Elevation line example on the iOS. Based on the GL-JS [sample](https://docs.mapbox.com/mapbox-gl-js/example/elevated-line/). ![image](https://github.com/user-attachments/assets/0c6f7c87-b8e8-4b79-ab59-145b18a5fd9d) MAPSIOS-1845 cc @mapbox/sdk-ci GitOrigin-RevId: 57891ab9c5b256c53065b3c94ab02e9724d1539a
1 parent 7b0634e commit dd2cdc5

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ mapView.mapboxMap.addInteraction(TapInteraction(.standardPoi) { poi, feature in
7070

7171
* Expose new experimental properties: `CircleLayer.circleElevationReference`, `FillLayer.fillConstructBridgeGuardRail`, `FillLayer.fillBridgeGuardRailColor`, `FillLayer.fillTunnelStructureColor`.
7272
* Expose new `showLandmarkIcons` property in `MapStyle.standard`.
73+
* New example for elevated spiral line. Utilized the experimental API `LineLayer/linezOffset`.
7374

7475
## 11.12.0 - 07 May, 2025
7576

Examples.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
2997D21A7DB20098C6D03D3B /* StandardStyleImportExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640198169EEDFC7CBEFCFCCF /* StandardStyleImportExample.swift */; };
3434
2B44F3E8EF3A50D9AE6B825F /* route.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 450C8D5E4B84428FE51BCA97 /* route.geojson */; };
3535
2C03342240D5487880316518 /* AddOneMarkerSymbolExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DCBE814694CF08A9C2E4A42 /* AddOneMarkerSymbolExample.swift */; platformFilters = (ios, ); };
36+
2EC3AAE5D54ACFB90E98CD43 /* ElevatedLineMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BBD2991186A6B98F730454 /* ElevatedLineMapView.swift */; };
3637
30589E5AB307FC934E466332 /* radar2.gif in Resources */ = {isa = PBXBuildFile; fileRef = D8730F8FB259A4F889609108 /* radar2.gif */; };
3738
312CE7CED726F0A572301622 /* PinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC3D7884D057238010CB6E4 /* PinView.swift */; };
3839
32FA2A4133B0464494212B34 /* Array+Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB15B17EDE597D37CFF3FCA /* Array+Split.swift */; };
@@ -182,6 +183,7 @@
182183
02DA2CC04980F807255D646B /* Fire_Hydrants.geojson */ = {isa = PBXFileReference; path = Fire_Hydrants.geojson; sourceTree = "<group>"; };
183184
06955521CCC52B47AAB475F4 /* CustomLayerExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayerExample.swift; sourceTree = "<group>"; };
184185
083C452C7342E73F6F16A83C /* OfflineManagerExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfflineManagerExample.swift; sourceTree = "<group>"; };
186+
09BBD2991186A6B98F730454 /* ElevatedLineMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElevatedLineMapView.swift; sourceTree = "<group>"; };
185187
0A5C0A3C44715B96D646ACB7 /* PitchAndDistanceExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PitchAndDistanceExample.swift; sourceTree = "<group>"; };
186188
0AD7661708AEADD25AB726B4 /* InstrumentClusterCarPlaySceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstrumentClusterCarPlaySceneDelegate.swift; sourceTree = "<group>"; };
187189
0FBAFDF929532EDB964786F4 /* StandardInteractiveFeaturesExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardInteractiveFeaturesExample.swift; sourceTree = "<group>"; };
@@ -413,6 +415,7 @@
413415
29DD4C2F0049E575A6B5BF66 /* ColorThemeExample.swift */,
414416
7DED80ACD1618F8EE8F95A4A /* CustomGeometrySourceExample.swift */,
415417
C61CC711054A032EE0446036 /* DynamicStylingExample.swift */,
418+
09BBD2991186A6B98F730454 /* ElevatedLineMapView.swift */,
416419
A6B06A1D70F479D8DC5C375A /* FeaturesQueryExample.swift */,
417420
7613C4E19DCD679A2620223C /* GeofencingPlayground.swift */,
418421
DD3A816C6E4D7A0A532EEE84 /* GeofencingUserLocation.swift */,
@@ -888,6 +891,7 @@
888891
CBCC60FF68BE9754DE0C6AF3 /* DynamicStylingExample.swift in Sources */,
889892
DFC64A62538E787D57B6514D /* DynamicViewAnnotationExample.swift in Sources */,
890893
000BBF0F3175DB2F54BFC85E /* EditPolygonExample.swift in Sources */,
894+
2EC3AAE5D54ACFB90E98CD43 /* ElevatedLineMapView.swift in Sources */,
891895
D62F69A9BD802A1926B92968 /* Example.swift in Sources */,
892896
10ECE7FE19CEC239DDA96961 /* ExampleProtocol.swift in Sources */,
893897
7B9835E597E0B2655E181A48 /* ExampleTableViewController.swift in Sources */,
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import SwiftUI
2+
import Turf
3+
@_spi(Experimental) import MapboxMaps
4+
5+
/// Native implementation for the [Add an elevated line to a map](https://docs.mapbox.com/mapbox-gl-js/example/elevated-line/)
6+
/// example from GL-JS 3.8
7+
struct ElevatedLineMapView: View {
8+
private let elevationPropertyKey = "elevation"
9+
private let lineSourceID = "geojson"
10+
private let lineLayerID = "elevated-line"
11+
12+
var body: some View {
13+
Map(initialViewport: .camera(
14+
center: CLLocationCoordinate2D(latitude: 45.8418, longitude: 6.7782),
15+
zoom: 11,
16+
bearing: -150,
17+
pitch: 62
18+
)) {
19+
StyleProjection(name: .mercator)
20+
21+
createGeoJSONSource()
22+
23+
LineLayer(id: lineLayerID, source: lineSourceID)
24+
.lineJoin(.round)
25+
.lineWidth(8)
26+
.lineColor(.blue)
27+
.lineEmissiveStrength(1.0)
28+
.lineElevationReference(.sea)
29+
.lineZOffset(
30+
Exp(.atInterpolated) {
31+
Exp(.product) {
32+
Exp(.lineProgress)
33+
Exp(.subtract, Exp(.length, Exp(.get, elevationPropertyKey)), 1)
34+
}
35+
Exp(.get, elevationPropertyKey)
36+
}
37+
)
38+
}
39+
.mapStyle(.standard)
40+
.ignoresSafeArea(.all)
41+
}
42+
43+
private func createGeoJSONSource() -> GeoJSONSource {
44+
var source = GeoJSONSource(id: lineSourceID)
45+
.data(createGeoJSON())
46+
source.lineMetrics = true
47+
return source
48+
}
49+
50+
private func createGeoJSON() -> GeoJSONSourceData {
51+
let feature = Feature(geometry: Geometry(LineString(coordinates)))
52+
.properties([
53+
elevationPropertyKey: .array(elevations.map {JSONValue(Double($0))})
54+
])
55+
56+
return .feature(feature)
57+
}
58+
59+
private let coordinates: [CLLocationCoordinate2D] = [
60+
CLLocationCoordinate2D(latitude: 45.833563, longitude: 6.862885),
61+
CLLocationCoordinate2D(latitude: 45.846851, longitude: 6.863605),
62+
CLLocationCoordinate2D(latitude: 45.862445, longitude: 6.859783),
63+
CLLocationCoordinate2D(latitude: 45.876361, longitude: 6.848727),
64+
CLLocationCoordinate2D(latitude: 45.892361, longitude: 6.827155),
65+
CLLocationCoordinate2D(latitude: 45.905032, longitude: 6.802194),
66+
CLLocationCoordinate2D(latitude: 45.909602, longitude: 6.780023),
67+
CLLocationCoordinate2D(latitude: 45.906074, longitude: 6.753605),
68+
CLLocationCoordinate2D(latitude: 45.899120, longitude: 6.728807),
69+
CLLocationCoordinate2D(latitude: 45.883872, longitude: 6.700449),
70+
CLLocationCoordinate2D(latitude: 45.863866, longitude: 6.683772),
71+
CLLocationCoordinate2D(latitude: 45.841619, longitude: 6.684058),
72+
CLLocationCoordinate2D(latitude: 45.825417, longitude: 6.691115),
73+
CLLocationCoordinate2D(latitude: 45.813349, longitude: 6.704446),
74+
CLLocationCoordinate2D(latitude: 45.807886, longitude: 6.720959),
75+
CLLocationCoordinate2D(latitude: 45.809517, longitude: 6.748477),
76+
CLLocationCoordinate2D(latitude: 45.817254, longitude: 6.775554),
77+
CLLocationCoordinate2D(latitude: 45.828871, longitude: 6.791236),
78+
CLLocationCoordinate2D(latitude: 45.838797, longitude: 6.801289),
79+
CLLocationCoordinate2D(latitude: 45.849788, longitude: 6.806307),
80+
CLLocationCoordinate2D(latitude: 45.866159, longitude: 6.803161),
81+
CLLocationCoordinate2D(latitude: 45.880461, longitude: 6.794599),
82+
CLLocationCoordinate2D(latitude: 45.890231, longitude: 6.769846),
83+
CLLocationCoordinate2D(latitude: 45.889576, longitude: 6.744712),
84+
CLLocationCoordinate2D(latitude: 45.881677, longitude: 6.722788),
85+
CLLocationCoordinate2D(latitude: 45.868556, longitude: 6.708097),
86+
CLLocationCoordinate2D(latitude: 45.851973, longitude: 6.699435),
87+
CLLocationCoordinate2D(latitude: 45.832980, longitude: 6.707324),
88+
CLLocationCoordinate2D(latitude: 45.822384, longitude: 6.723743),
89+
CLLocationCoordinate2D(latitude: 45.818626, longitude: 6.739347),
90+
CLLocationCoordinate2D(latitude: 45.822069, longitude: 6.756019),
91+
CLLocationCoordinate2D(latitude: 45.832436, longitude: 6.773963),
92+
CLLocationCoordinate2D(latitude: 45.848229, longitude: 6.785920),
93+
CLLocationCoordinate2D(latitude: 45.860521, longitude: 6.786155),
94+
CLLocationCoordinate2D(latitude: 45.870586, longitude: 6.774430),
95+
CLLocationCoordinate2D(latitude: 45.875670, longitude: 6.749012),
96+
CLLocationCoordinate2D(latitude: 45.868501, longitude: 6.731251),
97+
CLLocationCoordinate2D(latitude: 45.853689, longitude: 6.716033),
98+
CLLocationCoordinate2D(latitude: 45.846970, longitude: 6.714748),
99+
CLLocationCoordinate2D(latitude: 45.838934, longitude: 6.714635),
100+
CLLocationCoordinate2D(latitude: 45.832829, longitude: 6.717850),
101+
CLLocationCoordinate2D(latitude: 45.828151, longitude: 6.724010),
102+
CLLocationCoordinate2D(latitude: 45.827333, longitude: 6.730551),
103+
CLLocationCoordinate2D(latitude: 45.829900, longitude: 6.733951),
104+
CLLocationCoordinate2D(latitude: 45.834154, longitude: 6.735957),
105+
CLLocationCoordinate2D(latitude: 45.839871, longitude: 6.735286),
106+
CLLocationCoordinate2D(latitude: 45.843933, longitude: 6.734471),
107+
CLLocationCoordinate2D(latitude: 45.847233, longitude: 6.730893),
108+
CLLocationCoordinate2D(latitude: 45.847899, longitude: 6.728550),
109+
CLLocationCoordinate2D(latitude: 45.847822, longitude: 6.726590),
110+
CLLocationCoordinate2D(latitude: 45.846455, longitude: 6.724876),
111+
CLLocationCoordinate2D(latitude: 45.843900, longitude: 6.725096),
112+
CLLocationCoordinate2D(latitude: 45.841201, longitude: 6.726635),
113+
CLLocationCoordinate2D(latitude: 45.837041, longitude: 6.728074),
114+
CLLocationCoordinate2D(latitude: 45.834292, longitude: 6.727822),
115+
]
116+
117+
private let elevations = [
118+
4600, 4600, 4600, 4599, 4598, 4596, 4593, 4590, 4584, 4578, 4569,
119+
4559, 4547, 4533, 4516, 4497, 4475, 4450, 4422, 4390, 4355, 4316,
120+
4275, 4227, 4177, 4124, 4068, 4009, 3946, 3880, 3776, 3693, 3599,
121+
3502, 3398, 3290, 3171, 3052, 2922, 2786, 2642, 2490, 2332, 2170,
122+
1994, 1810, 1612, 1432, 1216, 1000
123+
]
124+
}

Sources/Examples/SwiftUI Examples/SwiftUIRoot.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ struct SwiftUIRoot: View {
3636
ExampleLink("Color Themes", note: "Showcase the Color Theme API", destination: ColorThemeExample())
3737
} header: { Text("Use cases") }
3838

39+
Section {
40+
ExampleLink("Line elevation", destination: ElevatedLineMapView())
41+
} header: { Text("🔬 Experimental APIs") }
42+
3943
Section {
4044
ExampleLink("Map settings", note: "Showcase of the most possible map configurations.", destination: MapSettingsExample())
4145
ExampleLink("Interactions playground", note: "Interactions edge cases", destination: InteractionsPlayground())

0 commit comments

Comments
 (0)