expo-arcgis 0.2.6 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisExtrasModule.kt +3 -5
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisGeometryModule.kt +8 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisMapView.kt +9 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisModule.kt +20 -1
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisSceneView.kt +10 -0
- package/android/src/main/java/expo/modules/arcgis/GraphicsOverlayRef.kt +17 -0
- package/android/src/main/java/expo/modules/arcgis/LayerRef.kt +85 -6
- package/android/src/main/java/expo/modules/arcgis/NetworkTrustHandler.kt +26 -0
- package/android/src/main/java/expo/modules/arcgis/OfflineFunctions.kt +12 -4
- package/android/src/main/java/expo/modules/arcgis/ServiceAreaFunctions.kt +61 -0
- package/build/DynamicEntityLayer.d.ts.map +1 -1
- package/build/ExpoArcgis.types.d.ts +109 -3
- package/build/ExpoArcgis.types.d.ts.map +1 -1
- package/build/ExpoArcgis.types.js.map +1 -1
- package/build/ExpoArcgisGeometryModule.d.ts +3 -1
- package/build/ExpoArcgisGeometryModule.d.ts.map +1 -1
- package/build/ExpoArcgisGeometryModule.js.map +1 -1
- package/build/ExpoArcgisModule.d.ts +23 -1
- package/build/ExpoArcgisModule.d.ts.map +1 -1
- package/build/ExpoArcgisModule.js.map +1 -1
- package/build/FeatureLayer.d.ts.map +1 -1
- package/build/auth.d.ts +12 -0
- package/build/auth.d.ts.map +1 -1
- package/build/auth.js +14 -0
- package/build/auth.js.map +1 -1
- package/build/index.d.ts +2 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/build/index.js.map +1 -1
- package/build/layers.d.ts +1 -0
- package/build/layers.d.ts.map +1 -1
- package/build/offline.d.ts +10 -2
- package/build/offline.d.ts.map +1 -1
- package/build/offline.js +5 -2
- package/build/offline.js.map +1 -1
- package/build/serviceArea.d.ts +15 -0
- package/build/serviceArea.d.ts.map +1 -0
- package/build/serviceArea.js +15 -0
- package/build/serviceArea.js.map +1 -0
- package/ios/ExpoArcgisExtrasModule.swift +3 -5
- package/ios/ExpoArcgisGeometryModule.swift +8 -0
- package/ios/ExpoArcgisMapView.swift +19 -1
- package/ios/ExpoArcgisModule.swift +22 -1
- package/ios/ExpoArcgisSceneView.swift +14 -0
- package/ios/GraphicsOverlayRef.swift +15 -0
- package/ios/LayerRef.swift +85 -5
- package/ios/NetworkTrustHandler.swift +18 -0
- package/ios/OfflineFunctions.swift +15 -4
- package/ios/ServiceAreaFunctions.swift +68 -0
- package/package.json +1 -1
- package/src/ExpoArcgis.types.ts +111 -3
- package/src/ExpoArcgisGeometryModule.ts +12 -0
- package/src/ExpoArcgisModule.ts +20 -1
- package/src/auth.ts +15 -0
- package/src/index.ts +2 -0
- package/src/offline.ts +16 -7
- package/src/serviceArea.ts +17 -0
|
@@ -47,6 +47,9 @@ class ExpoArcgisExtrasModule : Module() {
|
|
|
47
47
|
AsyncFunction("addFeatureWithSubtype") Coroutine { ref: FeatureLayerRef, subtypeName: String, attributes: Map<String, Any?>?, geometry: Map<String, Any?>?, apply: Boolean? ->
|
|
48
48
|
ref.addFeatureWithSubtype(subtypeName, attributes, geometry, apply)
|
|
49
49
|
}
|
|
50
|
+
AsyncFunction("contingentValues") Coroutine { ref: FeatureLayerRef, attributes: Map<String, Any?>, fieldName: String ->
|
|
51
|
+
ref.contingentValues(attributes, fieldName)
|
|
52
|
+
}
|
|
50
53
|
AsyncFunction("getContingentValues") Coroutine { ref: FeatureLayerRef, objectId: Long, fieldName: String ->
|
|
51
54
|
ref.getContingentValues(objectId, fieldName)
|
|
52
55
|
}
|
|
@@ -93,11 +96,6 @@ class ExpoArcgisExtrasModule : Module() {
|
|
|
93
96
|
.getOrThrow()
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
// Tile-cache size estimation — quick estimate before committing to a download.
|
|
97
|
-
AsyncFunction("estimateTileCacheSize") Coroutine { tileServiceUrl: String, areaOfInterest: Map<String, Any?>, options: Map<String, Any?>? ->
|
|
98
|
-
estimateTileCacheSize(tileServiceUrl, areaOfInterest, options)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
99
|
// Turn-by-turn navigation — solve a route and track device locations against it.
|
|
102
100
|
AsyncFunction("createRouteTracker") Coroutine { stops: List<Map<String, Any?>>, params: Map<String, Any?> ->
|
|
103
101
|
createRouteTracker(appContext, stops, params)
|
|
@@ -96,6 +96,11 @@ class ExpoArcgisGeometryModule : Module() {
|
|
|
96
96
|
solveRoute(stops, params)
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// Service Area — compute reachable areas from facilities, exposed as the JS `serviceArea` namespace.
|
|
100
|
+
AsyncFunction("serviceAreaSolve") Coroutine { params: Map<String, Any?> ->
|
|
101
|
+
serviceAreaSolve(params)
|
|
102
|
+
}
|
|
103
|
+
|
|
99
104
|
// Geoprocessing — run a geoprocessing service, exposed as the JS `geoprocessor` namespace.
|
|
100
105
|
AsyncFunction("executeGeoprocessing") Coroutine { serviceUrl: String, inputs: Map<String, Any?> ->
|
|
101
106
|
executeGeoprocessing(appContext, serviceUrl, inputs)
|
|
@@ -215,5 +220,8 @@ class ExpoArcgisGeometryModule : Module() {
|
|
|
215
220
|
AsyncFunction("exportVectorTiles") Coroutine { vectorTileServiceUrl: String, areaOfInterest: Map<String, Any?>, downloadName: String ->
|
|
216
221
|
exportVectorTiles(appContext, appContext.reactContext?.filesDir, vectorTileServiceUrl, areaOfInterest, downloadName)
|
|
217
222
|
}
|
|
223
|
+
AsyncFunction("estimateTileCacheSize") Coroutine { tileServiceUrl: String, areaOfInterest: Map<String, Any?>, minScale: Double?, maxScale: Double? ->
|
|
224
|
+
estimateTileCacheSize(tileServiceUrl, areaOfInterest, minScale, maxScale)
|
|
225
|
+
}
|
|
218
226
|
}
|
|
219
227
|
}
|
|
@@ -15,6 +15,7 @@ import com.arcgismaps.location.SimulatedLocationDataSource
|
|
|
15
15
|
import com.arcgismaps.location.SimulationParameters
|
|
16
16
|
import com.arcgismaps.location.SystemLocationDataSource
|
|
17
17
|
import java.time.Instant
|
|
18
|
+
import com.arcgismaps.mapping.TimeExtent
|
|
18
19
|
import com.arcgismaps.mapping.Viewpoint
|
|
19
20
|
import com.arcgismaps.mapping.view.MapView
|
|
20
21
|
import com.arcgismaps.mapping.view.ScreenCoordinate
|
|
@@ -151,6 +152,14 @@ class ExpoArcgisMapView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
151
152
|
?: com.arcgismaps.mapping.view.LatitudeLongitudeGrid().apply { isVisible = false }
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
/** Filters time-aware layers to a time window from JS (null shows all time steps). */
|
|
156
|
+
fun setTimeExtent(config: Map<String, Any?>?) {
|
|
157
|
+
if (config == null) { mapView.setTimeExtent(null); return }
|
|
158
|
+
val startMs = (config["startTime"] as? Number)?.toLong() ?: return
|
|
159
|
+
val endMs = (config["endTime"] as? Number)?.toLong() ?: return
|
|
160
|
+
mapView.setTimeExtent(TimeExtent(Instant.ofEpochMilli(startMs), Instant.ofEpochMilli(endMs)))
|
|
161
|
+
}
|
|
162
|
+
|
|
154
163
|
/** Enables/configures the device location display from JS (null disables it). */
|
|
155
164
|
fun setLocationDisplay(config: Map<String, Any?>?) {
|
|
156
165
|
val locationDisplay = mapView.locationDisplay
|
|
@@ -40,6 +40,13 @@ class ExpoArcgisModule : Module() {
|
|
|
40
40
|
AuthChallengeHandler.setCredentials(username, password, tokenExpirationMinutes)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// Network-layer server-trust override — for on-prem ArcGIS Enterprise with self-signed certs.
|
|
44
|
+
// NEVER enable in production: disabling TLS validation exposes connections to MITM attacks.
|
|
45
|
+
Function("setAllowUntrustedHosts") { allow: Boolean ->
|
|
46
|
+
ArcGISEnvironment.authenticationManager.networkAuthenticationChallengeHandler =
|
|
47
|
+
if (allow) NetworkTrustHandler else null
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
// Revokes any OAuth user credentials on the server, then clears all cached credentials.
|
|
44
51
|
AsyncFunction("signOut") Coroutine { ->
|
|
45
52
|
val store = ArcGISEnvironment.authenticationManager.arcGISCredentialStore
|
|
@@ -210,7 +217,8 @@ class ExpoArcgisModule : Module() {
|
|
|
210
217
|
Constructor { props: Map<String, Any?> ->
|
|
211
218
|
@Suppress("UNCHECKED_CAST")
|
|
212
219
|
val source = props["source"] as? Map<String, Any?> ?: emptyMap()
|
|
213
|
-
|
|
220
|
+
val rasterFunctionJson = props["rasterFunction"] as? String
|
|
221
|
+
RasterLayerRef(appContext, source, rasterFunctionJson).also { it.applyProps(props) }
|
|
214
222
|
}
|
|
215
223
|
Function("applyProps") { ref: RasterLayerRef, changed: Map<String, Any?> ->
|
|
216
224
|
ref.applyProps(changed)
|
|
@@ -225,6 +233,9 @@ class ExpoArcgisModule : Module() {
|
|
|
225
233
|
ref.applyProps(changed)
|
|
226
234
|
}
|
|
227
235
|
AsyncFunction("getNodes") Coroutine { ref: KmlLayerRef -> ref.getNodes() }
|
|
236
|
+
Function("playTour") { ref: KmlLayerRef -> ref.playTour() }
|
|
237
|
+
Function("pauseTour") { ref: KmlLayerRef -> ref.pauseTour() }
|
|
238
|
+
Function("resetTour") { ref: KmlLayerRef -> ref.resetTour() }
|
|
228
239
|
}
|
|
229
240
|
|
|
230
241
|
// WFS (Web Feature Service) + OGC API - Features — feature layers over async-populating tables.
|
|
@@ -385,6 +396,10 @@ class ExpoArcgisModule : Module() {
|
|
|
385
396
|
view.setGrid(grid)
|
|
386
397
|
}
|
|
387
398
|
|
|
399
|
+
Prop("timeExtent") { view: ExpoArcgisMapView, value: Map<String, Any?>? ->
|
|
400
|
+
view.setTimeExtent(value)
|
|
401
|
+
}
|
|
402
|
+
|
|
388
403
|
AsyncFunction("identify") { view: ExpoArcgisMapView, screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise ->
|
|
389
404
|
view.identify(screenPoint, options, promise)
|
|
390
405
|
}
|
|
@@ -451,6 +466,10 @@ class ExpoArcgisModule : Module() {
|
|
|
451
466
|
view.setSunTime(value)
|
|
452
467
|
}
|
|
453
468
|
|
|
469
|
+
Prop("timeExtent") { view: ExpoArcgisSceneView, value: Map<String, Any?>? ->
|
|
470
|
+
view.setTimeExtent(value)
|
|
471
|
+
}
|
|
472
|
+
|
|
454
473
|
AsyncFunction("retryLoad") { view: ExpoArcgisSceneView, promise: Promise ->
|
|
455
474
|
view.retryLoad(promise)
|
|
456
475
|
}
|
|
@@ -7,7 +7,9 @@ import androidx.lifecycle.findViewTreeLifecycleOwner
|
|
|
7
7
|
import com.arcgismaps.geometry.GeometryEngine
|
|
8
8
|
import com.arcgismaps.geometry.Point
|
|
9
9
|
import com.arcgismaps.geometry.SpatialReference
|
|
10
|
+
import com.arcgismaps.mapping.TimeExtent
|
|
10
11
|
import com.arcgismaps.mapping.view.AtmosphereEffect
|
|
12
|
+
import java.time.Instant
|
|
11
13
|
import com.arcgismaps.mapping.view.Camera
|
|
12
14
|
import com.arcgismaps.mapping.view.GlobeCameraController
|
|
13
15
|
import com.arcgismaps.mapping.view.LightingMode
|
|
@@ -230,6 +232,14 @@ class ExpoArcgisSceneView(context: Context, appContext: AppContext) : ExpoView(c
|
|
|
230
232
|
sceneView.sunTime = java.time.Instant.ofEpochMilli(ms.toLong())
|
|
231
233
|
}
|
|
232
234
|
|
|
235
|
+
/** Filters time-aware layers to a time window from JS (null shows all time steps). */
|
|
236
|
+
fun setTimeExtent(config: Map<String, Any?>?) {
|
|
237
|
+
if (config == null) { sceneView.setTimeExtent(null); return }
|
|
238
|
+
val startMs = (config["startTime"] as? Number)?.toLong() ?: return
|
|
239
|
+
val endMs = (config["endTime"] as? Number)?.toLong() ?: return
|
|
240
|
+
sceneView.setTimeExtent(TimeExtent(Instant.ofEpochMilli(startMs), Instant.ofEpochMilli(endMs)))
|
|
241
|
+
}
|
|
242
|
+
|
|
233
243
|
override fun onAttachedToWindow() {
|
|
234
244
|
super.onAttachedToWindow()
|
|
235
245
|
val lifecycle = findViewTreeLifecycleOwner()?.lifecycle
|
|
@@ -18,8 +18,10 @@ import com.arcgismaps.mapping.symbology.SimpleLineSymbol
|
|
|
18
18
|
import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle
|
|
19
19
|
import com.arcgismaps.mapping.symbology.DistanceCompositeSceneSymbol
|
|
20
20
|
import com.arcgismaps.mapping.symbology.DistanceSymbolRange
|
|
21
|
+
import com.arcgismaps.mapping.symbology.ModelSceneSymbol
|
|
21
22
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbol
|
|
22
23
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbolStyle
|
|
24
|
+
import com.arcgismaps.mapping.symbology.SymbolSizeUnits
|
|
23
25
|
import com.arcgismaps.mapping.symbology.MultilayerPointSymbol
|
|
24
26
|
import com.arcgismaps.mapping.symbology.MultilayerPolygonSymbol
|
|
25
27
|
import com.arcgismaps.mapping.symbology.MultilayerPolylineSymbol
|
|
@@ -346,6 +348,21 @@ private fun buildSymbol(s: Map<*, *>): Symbol? = when (s["type"]) {
|
|
|
346
348
|
num(s["depth"], 100.0),
|
|
347
349
|
sceneSymbolAnchor(s["anchor"]),
|
|
348
350
|
)
|
|
351
|
+
"model-scene" -> (s["url"] as? String)?.let { rawUri ->
|
|
352
|
+
// ModelSceneSymbol(uri, scale) — 3D glTF/model marker. ArcGIS on Android resolves a LOCAL model
|
|
353
|
+
// by filesystem path, so an expo `file://` URI must be unwrapped (iOS `URL(string:)` accepts the
|
|
354
|
+
// scheme, Android silently fails to load it). Set heading/pitch/roll (Float) + symbolSizeUnits;
|
|
355
|
+
// the symbol is Loadable.
|
|
356
|
+
val uri = if (rawUri.startsWith("file://")) android.net.Uri.parse(rawUri).path ?: rawUri else rawUri
|
|
357
|
+
val scale = (s["scale"] as? Number)?.toFloat() ?: 1f
|
|
358
|
+
ModelSceneSymbol(uri, scale).apply {
|
|
359
|
+
symbolSizeUnits = if (s["sizeUnits"] == "meters") SymbolSizeUnits.Meters else SymbolSizeUnits.Dips
|
|
360
|
+
heading = (s["heading"] as? Number)?.toFloat() ?: 0f
|
|
361
|
+
pitch = (s["pitch"] as? Number)?.toFloat() ?: 0f
|
|
362
|
+
roll = (s["roll"] as? Number)?.toFloat() ?: 0f
|
|
363
|
+
anchorPosition = sceneSymbolAnchor(s["anchor"])
|
|
364
|
+
}
|
|
365
|
+
}
|
|
349
366
|
"picture-marker" -> (s["url"] as? String)?.let { url ->
|
|
350
367
|
PictureMarkerSymbol(url).apply {
|
|
351
368
|
(s["width"] as? Number)?.toFloat()?.let { width = it }
|
|
@@ -57,9 +57,12 @@ import com.arcgismaps.mapping.layers.WmtsLayer
|
|
|
57
57
|
import com.arcgismaps.mapping.kml.KmlContainer
|
|
58
58
|
import com.arcgismaps.mapping.kml.KmlDataset
|
|
59
59
|
import com.arcgismaps.mapping.kml.KmlNode
|
|
60
|
+
import com.arcgismaps.mapping.kml.KmlTour
|
|
61
|
+
import com.arcgismaps.mapping.kml.KmlTourController
|
|
60
62
|
import com.arcgismaps.mapping.view.Graphic
|
|
61
63
|
import com.arcgismaps.raster.ImageServiceRaster
|
|
62
64
|
import com.arcgismaps.raster.Raster
|
|
65
|
+
import com.arcgismaps.raster.RasterFunction
|
|
63
66
|
import expo.modules.kotlin.AppContext
|
|
64
67
|
import expo.modules.kotlin.sharedobjects.SharedObject
|
|
65
68
|
|
|
@@ -290,6 +293,38 @@ class FeatureLayerRef(appContext: AppContext, private val table: FeatureTable) :
|
|
|
290
293
|
persistEdits()
|
|
291
294
|
}
|
|
292
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Returns the valid coded values for [fieldName] given a feature's current [attributes].
|
|
298
|
+
* Use this to drive editing-form dropdowns: pass the feature's current attribute state and the
|
|
299
|
+
* name of the field being edited; returns `[{ name, code }]` for coded values that satisfy all
|
|
300
|
+
* contingent-value constraints defined on the table.
|
|
301
|
+
*
|
|
302
|
+
* Loads the table and its [ContingentValuesDefinition], builds a temporary [ArcGISFeature] from
|
|
303
|
+
* [attributes] (via `FeatureTable.createFeature(attributes, null)` + `applyAttributes`), then
|
|
304
|
+
* calls `getContingentValuesOrNull(feature, fieldName)`.
|
|
305
|
+
* Non-coded contingent values ([ContingentRangeValue], null, any) are omitted — only
|
|
306
|
+
* [ContingentCodedValue] entries are returned.
|
|
307
|
+
*
|
|
308
|
+
* Requires an [ArcGISFeatureTable]; throws for shapefiles and WFS tables.
|
|
309
|
+
* Returns an empty list when no constraints are defined for [fieldName].
|
|
310
|
+
*/
|
|
311
|
+
suspend fun contingentValues(attributes: Map<String, Any?>, fieldName: String): List<Map<String, Any?>> {
|
|
312
|
+
table.load().getOrThrow()
|
|
313
|
+
val arcGISTable = table as? ArcGISFeatureTable
|
|
314
|
+
?: throw IllegalStateException("contingentValues requires an ArcGIS feature table (not a shapefile or WFS table)")
|
|
315
|
+
arcGISTable.contingentValuesDefinition.load().getOrThrow()
|
|
316
|
+
val feature = table.createFeature(attributes, null) as ArcGISFeature
|
|
317
|
+
val result = arcGISTable.getContingentValuesOrNull(feature, fieldName)
|
|
318
|
+
?: return emptyList()
|
|
319
|
+
return result.byFieldGroup.flatMap { (_, values) ->
|
|
320
|
+
values.mapNotNull { cv ->
|
|
321
|
+
if (cv !is ContingentCodedValue) return@mapNotNull null
|
|
322
|
+
val coded = cv.codedValue
|
|
323
|
+
mapOf("name" to coded.name, "code" to coded.code)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
293
328
|
/**
|
|
294
329
|
* Returns the valid contingent values for [fieldName] on the feature with [objectId].
|
|
295
330
|
* Requires the table to be an [ArcGISFeatureTable]; throws otherwise. Returns an empty list when
|
|
@@ -537,21 +572,41 @@ class WmtsLayerRef(appContext: AppContext, url: String, layerId: String) : Layer
|
|
|
537
572
|
}
|
|
538
573
|
|
|
539
574
|
/** Operational raster layer from a remote image service or a local raster file. */
|
|
540
|
-
class RasterLayerRef(
|
|
541
|
-
|
|
575
|
+
class RasterLayerRef(
|
|
576
|
+
appContext: AppContext,
|
|
577
|
+
source: Map<String, Any?>,
|
|
578
|
+
rasterFunctionJson: String? = null,
|
|
579
|
+
) : LayerRef(appContext) {
|
|
580
|
+
override val layer: RasterLayer = RasterLayer(rasterFromSource(source, rasterFunctionJson))
|
|
542
581
|
|
|
543
582
|
override fun applyProps(changed: Map<String, Any?>) = applyCommonProps(changed)
|
|
544
583
|
}
|
|
545
584
|
|
|
546
|
-
/**
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
585
|
+
/**
|
|
586
|
+
* Builds a [Raster] from a JS source dict: `{type:"imageService",url}` or `{type:"file",path}`.
|
|
587
|
+
* When [rasterFunctionJson] is supplied, wraps the base raster in a [RasterFunction] pipeline:
|
|
588
|
+
* `RasterFunction.fromJsonOrNull` → wire source raster as first raster argument →
|
|
589
|
+
* `Raster.createWithRasterFunction`. Falls back to the plain source raster if parsing fails
|
|
590
|
+
* or no raster argument is found.
|
|
591
|
+
*/
|
|
592
|
+
private fun rasterFromSource(s: Map<String, Any?>, rasterFunctionJson: String? = null): Raster {
|
|
593
|
+
val base: Raster =
|
|
594
|
+
if (s["type"] == "file") Raster.createWithPath(s["path"] as? String ?: "")
|
|
595
|
+
else ImageServiceRaster(s["url"] as? String ?: "")
|
|
596
|
+
if (rasterFunctionJson == null) return base
|
|
597
|
+
val fn = RasterFunction.fromJsonOrNull(rasterFunctionJson) ?: return base
|
|
598
|
+
val args = fn.arguments ?: return base
|
|
599
|
+
val firstName = args.rasterNames.firstOrNull() ?: return base
|
|
600
|
+
args.setRaster(firstName, base)
|
|
601
|
+
return Raster.createWithRasterFunction(fn)
|
|
602
|
+
}
|
|
550
603
|
|
|
551
604
|
/** Operational KML layer from a remote .kml/.kmz URL or local file. */
|
|
552
605
|
class KmlLayerRef(appContext: AppContext, url: String) : LayerRef(appContext) {
|
|
553
606
|
private val dataset = KmlDataset(url)
|
|
554
607
|
override val layer: KmlLayer = KmlLayer(dataset)
|
|
608
|
+
/** Lazily-created controller; held for the lifetime of the ref so play/pause/reset are idempotent. */
|
|
609
|
+
private var tourController: KmlTourController? = null
|
|
555
610
|
|
|
556
611
|
override fun applyProps(changed: Map<String, Any?>) = applyCommonProps(changed)
|
|
557
612
|
|
|
@@ -560,6 +615,21 @@ class KmlLayerRef(appContext: AppContext, url: String) : LayerRef(appContext) {
|
|
|
560
615
|
dataset.load().getOrThrow()
|
|
561
616
|
return dataset.rootNodes.map { serializeKmlNode(it) }
|
|
562
617
|
}
|
|
618
|
+
|
|
619
|
+
/** Returns the existing controller, or creates one attached to the first [KmlTour] in the node tree.
|
|
620
|
+
* Returns `null` if the dataset has no tour. */
|
|
621
|
+
private fun controller(): KmlTourController? {
|
|
622
|
+
tourController?.let { return it }
|
|
623
|
+
val tour = findFirstTour(dataset.rootNodes) ?: return null
|
|
624
|
+
return KmlTourController().also { it.tour = tour; tourController = it }
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/** Starts or resumes playback of the first KML tour. No-ops if no tour exists. */
|
|
628
|
+
fun playTour() { controller()?.play() }
|
|
629
|
+
/** Pauses playback of the first KML tour. No-ops if no tour exists. */
|
|
630
|
+
fun pauseTour() { controller()?.pause() }
|
|
631
|
+
/** Resets playback of the first KML tour to the beginning. No-ops if no tour exists. */
|
|
632
|
+
fun resetTour() { controller()?.reset() }
|
|
563
633
|
}
|
|
564
634
|
|
|
565
635
|
/** Serializes a KML node, recursing into container nodes (documents / folders). */
|
|
@@ -575,6 +645,15 @@ private fun serializeKmlNode(node: KmlNode): Map<String, Any?> {
|
|
|
575
645
|
return dict
|
|
576
646
|
}
|
|
577
647
|
|
|
648
|
+
/** Depth-first search for the first [KmlTour] in a list of KML nodes. */
|
|
649
|
+
private fun findFirstTour(nodes: List<KmlNode>): KmlTour? {
|
|
650
|
+
for (node in nodes) {
|
|
651
|
+
if (node is KmlTour) return node
|
|
652
|
+
if (node is KmlContainer) findFirstTour(node.childNodes)?.let { return it }
|
|
653
|
+
}
|
|
654
|
+
return null
|
|
655
|
+
}
|
|
656
|
+
|
|
578
657
|
/** Operational WFS layer — a [FeatureLayer] over a [WfsFeatureTable] (Web Feature Service). */
|
|
579
658
|
class WfsLayerRef(appContext: AppContext, url: String, tableName: String) : LayerRef(appContext) {
|
|
580
659
|
override val layer: FeatureLayer = FeatureLayer.createWithFeatureTable(
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import com.arcgismaps.httpcore.authentication.NetworkAuthenticationChallenge
|
|
4
|
+
import com.arcgismaps.httpcore.authentication.NetworkAuthenticationChallengeHandler
|
|
5
|
+
import com.arcgismaps.httpcore.authentication.NetworkAuthenticationChallengeResponse
|
|
6
|
+
import com.arcgismaps.httpcore.authentication.NetworkAuthenticationType
|
|
7
|
+
import com.arcgismaps.httpcore.authentication.ServerTrust
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Network-layer trust handler that accepts every server-trust challenge unconditionally.
|
|
11
|
+
* Only install this for development or on-prem ArcGIS Enterprise with self-signed certificates —
|
|
12
|
+
* it disables TLS certificate validation, which makes the connection vulnerable to
|
|
13
|
+
* man-in-the-middle attacks. Never enable in production.
|
|
14
|
+
*/
|
|
15
|
+
object NetworkTrustHandler : NetworkAuthenticationChallengeHandler {
|
|
16
|
+
override suspend fun handleNetworkAuthenticationChallenge(
|
|
17
|
+
challenge: NetworkAuthenticationChallenge,
|
|
18
|
+
): NetworkAuthenticationChallengeResponse {
|
|
19
|
+
if (challenge.networkAuthenticationType is NetworkAuthenticationType.ServerTrust) {
|
|
20
|
+
return NetworkAuthenticationChallengeResponse.ContinueWithCredential(ServerTrust)
|
|
21
|
+
}
|
|
22
|
+
// Other challenge kinds (basic / digest / NTLM / client-cert) aren't ours to satisfy — continue
|
|
23
|
+
// without a credential (mirrors Swift's `.continueWithoutCredential`) instead of cancelling them.
|
|
24
|
+
return NetworkAuthenticationChallengeResponse.ContinueAndFail
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -209,20 +209,28 @@ internal suspend fun exportTileCache(
|
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* Estimates the on-disk file size and tile count for an [exportTileCache] download WITHOUT
|
|
212
|
-
* downloading.
|
|
212
|
+
* downloading. Passes [minScale]/[maxScale] (0.0 = no limit) to
|
|
213
|
+
* [ExportTileCacheTask.createDefaultExportTileCacheParameters] to narrow the estimation to the
|
|
214
|
+
* same scale window that [exportTileCache] would use. Runs the [EstimateTileCacheSizeJob] to
|
|
215
|
+
* completion and returns `{fileSizeBytes, tileCount}`.
|
|
213
216
|
*/
|
|
214
217
|
internal suspend fun estimateTileCacheSize(
|
|
215
218
|
tileServiceUrl: String,
|
|
216
219
|
areaOfInterest: Map<String, Any?>,
|
|
217
|
-
|
|
220
|
+
minScale: Double?,
|
|
221
|
+
maxScale: Double?,
|
|
218
222
|
): Map<String, Any?> {
|
|
219
223
|
val area = geometryFromDict(areaOfInterest) ?: throw IllegalArgumentException("Invalid area of interest")
|
|
220
224
|
val task = ExportTileCacheTask(tileServiceUrl)
|
|
221
|
-
val parameters = task.createDefaultExportTileCacheParameters(
|
|
225
|
+
val parameters = task.createDefaultExportTileCacheParameters(
|
|
226
|
+
area,
|
|
227
|
+
minScale ?: 0.0,
|
|
228
|
+
maxScale ?: 0.0,
|
|
229
|
+
).getOrThrow()
|
|
222
230
|
val job = task.createEstimateTileCacheSizeJob(parameters)
|
|
223
231
|
job.start()
|
|
224
232
|
val estimate = job.result().getOrThrow()
|
|
225
|
-
return mapOf("
|
|
233
|
+
return mapOf("fileSizeBytes" to estimate.fileSize.toDouble(), "tileCount" to estimate.tileCount.toDouble())
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
internal suspend fun exportVectorTiles(
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import com.arcgismaps.tasks.networkanalysis.ServiceAreaFacility
|
|
4
|
+
import com.arcgismaps.tasks.networkanalysis.ServiceAreaPolygon
|
|
5
|
+
import com.arcgismaps.tasks.networkanalysis.ServiceAreaResult
|
|
6
|
+
import com.arcgismaps.tasks.networkanalysis.ServiceAreaTask
|
|
7
|
+
import com.arcgismaps.geometry.Point
|
|
8
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Free functions backing the JS `serviceArea` namespace — computing reachable areas from
|
|
12
|
+
* facilities via a [ServiceAreaTask]. Registered as an `AsyncFunction` in
|
|
13
|
+
* `ExpoArcgisGeometryModule`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Caches one [ServiceAreaTask] per service URL so repeated solves don't reload service metadata. */
|
|
17
|
+
private val serviceAreaTasks = ConcurrentHashMap<String, ServiceAreaTask>()
|
|
18
|
+
|
|
19
|
+
private fun serviceAreaTask(url: String): ServiceAreaTask =
|
|
20
|
+
serviceAreaTasks.getOrPut(url) { ServiceAreaTask(url) }
|
|
21
|
+
|
|
22
|
+
internal suspend fun serviceAreaSolve(params: Map<String, Any?>): Map<String, Any?> {
|
|
23
|
+
val serviceUrl = params["serviceUrl"] as? String
|
|
24
|
+
?: error("serviceUrl is required")
|
|
25
|
+
val task = serviceAreaTask(serviceUrl)
|
|
26
|
+
// createDefaultParameters() loads the task so the service metadata is populated afterwards.
|
|
27
|
+
val parameters = task.createDefaultParameters().getOrThrow()
|
|
28
|
+
val facilitiesDicts = params["facilities"] as? List<*> ?: emptyList<Any?>()
|
|
29
|
+
parameters.setFacilities(buildFacilities(facilitiesDicts))
|
|
30
|
+
(params["cutoffs"] as? List<*>)?.let { rawCutoffs ->
|
|
31
|
+
val cutoffs = rawCutoffs.mapNotNull { (it as? Number)?.toDouble() }
|
|
32
|
+
if (cutoffs.isNotEmpty()) {
|
|
33
|
+
// ServiceAreaParameters.defaultImpedanceCutoffs is a mutable live list (no setter / add API).
|
|
34
|
+
parameters.defaultImpedanceCutoffs.clear()
|
|
35
|
+
parameters.defaultImpedanceCutoffs.addAll(cutoffs)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
val result = task.solveServiceArea(parameters).getOrThrow()
|
|
39
|
+
return serializeServiceAreaResult(result)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private fun buildFacilities(dicts: List<*>): List<ServiceAreaFacility> =
|
|
43
|
+
dicts.filterIsInstance<Map<*, *>>().mapNotNull { dict ->
|
|
44
|
+
(geometryFromDict(dict) as? Point)?.let { ServiceAreaFacility(it) }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private fun serializeServiceAreaResult(result: ServiceAreaResult): Map<String, Any?> {
|
|
48
|
+
val polygons = mutableListOf<Map<String, Any?>>()
|
|
49
|
+
for ((index, _) in result.facilities.withIndex()) {
|
|
50
|
+
for (polygon in result.getResultPolygons(index)) {
|
|
51
|
+
polygons.add(serializeServiceAreaPolygon(polygon))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return mapOf("polygons" to polygons)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private fun serializeServiceAreaPolygon(polygon: ServiceAreaPolygon): Map<String, Any?> = mapOf(
|
|
58
|
+
"geometry" to dictFromGeometry(polygon.geometry),
|
|
59
|
+
"fromCutoff" to polygon.fromImpedanceCutoff,
|
|
60
|
+
"toCutoff" to polygon.toImpedanceCutoff,
|
|
61
|
+
)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAQ5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;
|
|
1
|
+
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAQ5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;mBAwDoguC,CAAC;gBAAkB,CAAC;;;;;;;4DADtjuC,CAAC"}
|
|
@@ -131,6 +131,15 @@ export type MapViewProps = {
|
|
|
131
131
|
viewpoint?: Viewpoint;
|
|
132
132
|
/** Device-location display. When set, the view shows the device's GPS location. */
|
|
133
133
|
locationDisplay?: LocationDisplay;
|
|
134
|
+
/**
|
|
135
|
+
* Filters time-aware layers to this time window. Both values are epoch milliseconds (UTC).
|
|
136
|
+
* Pass `null` / omit to show all time steps (no filter). Maps to `GeoView.timeExtent` /
|
|
137
|
+
* `MapView(timeExtent:)` on both platforms.
|
|
138
|
+
*/
|
|
139
|
+
timeExtent?: {
|
|
140
|
+
startTime: number;
|
|
141
|
+
endTime: number;
|
|
142
|
+
} | null;
|
|
134
143
|
/** Called once the map has finished loading successfully. */
|
|
135
144
|
onMapLoaded?: (event: {
|
|
136
145
|
nativeEvent: MapLoadedEventPayload;
|
|
@@ -640,6 +649,26 @@ export type FeatureLayerHandle = {
|
|
|
640
649
|
* feature layer. The same handle is returned on repeat calls.
|
|
641
650
|
*/
|
|
642
651
|
getServiceGeodatabase(): Promise<ServiceGeodatabaseHandle>;
|
|
652
|
+
/**
|
|
653
|
+
* Returns the valid coded values for `fieldName` given the feature's current `attributes`.
|
|
654
|
+
* Use this to drive editing-form dropdowns: pass the feature's current attribute state and the
|
|
655
|
+
* name of the field being edited; returns `[{ name, code }]` for coded values that satisfy all
|
|
656
|
+
* contingent-value constraints defined on the table.
|
|
657
|
+
*
|
|
658
|
+
* The table and its `ContingentValuesDefinition` are loaded automatically. A temporary feature
|
|
659
|
+
* is built from `attributes` (no server round-trip for the feature itself); only `ArcGISFeature`
|
|
660
|
+
* tables are supported — rejects for shapefiles and WFS tables.
|
|
661
|
+
*
|
|
662
|
+
* @example
|
|
663
|
+
* ```ts
|
|
664
|
+
* const options = await layer.current.contingentValues({ habitat: 'oak' }, 'species');
|
|
665
|
+
* // options → [{ name: 'Red Oak', code: 1 }, { name: 'White Oak', code: 2 }]
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
contingentValues(attributes: Record<string, unknown>, fieldName: string): Promise<{
|
|
669
|
+
name: string;
|
|
670
|
+
code: unknown;
|
|
671
|
+
}[]>;
|
|
643
672
|
/**
|
|
644
673
|
* Returns the valid contingent values for `fieldName` on the feature with `objectId`, given
|
|
645
674
|
* the feature's current attribute state. Contingent values constrain which attribute values
|
|
@@ -811,6 +840,14 @@ export type RasterSource = {
|
|
|
811
840
|
/** Props for a `<RasterLayer>` — mirror the native `RasterLayer` (image service or local raster). */
|
|
812
841
|
export type RasterLayerProps = LayerProps & {
|
|
813
842
|
source: RasterSource;
|
|
843
|
+
/**
|
|
844
|
+
* On-the-fly raster function chain to apply to the layer's raster, serialised as JSON
|
|
845
|
+
* (e.g. a hillshade / colormap / NDVI chain). When set, the SDK builds a
|
|
846
|
+
* `RasterFunction.fromJSON` → `Raster(rasterFunction:)` pipeline with the source raster
|
|
847
|
+
* wired in as the first raster argument. Construction-time only — changing this prop
|
|
848
|
+
* requires remounting the layer.
|
|
849
|
+
*/
|
|
850
|
+
rasterFunction?: string;
|
|
814
851
|
};
|
|
815
852
|
/** Props for a `<KmlLayer>` — mirror `KMLLayer` (remote `.kml`/`.kmz` URL or local file). */
|
|
816
853
|
export type KmlLayerProps = LayerProps & {
|
|
@@ -1054,10 +1091,23 @@ export type KmlNodeInfo = {
|
|
|
1054
1091
|
/** Child nodes, present for container nodes (documents / folders). */
|
|
1055
1092
|
children?: KmlNodeInfo[];
|
|
1056
1093
|
};
|
|
1057
|
-
/**
|
|
1094
|
+
/**
|
|
1095
|
+
* Imperative handle exposed by `<KmlLayer>` via `ref`.
|
|
1096
|
+
*
|
|
1097
|
+
* **Tour playback (`playTour` / `pauseTour` / `resetTour`) is iOS-only.** On Android the tour
|
|
1098
|
+
* controller cannot drive the camera of the view-based scene view (an ArcGIS Maps SDK limitation —
|
|
1099
|
+
* automatic tour playback exists only on the Compose `SceneView`, and the controller exposes no
|
|
1100
|
+
* camera/viewpoint to drive it manually). The methods are present on Android but no-op visually.
|
|
1101
|
+
*/
|
|
1058
1102
|
export type KmlLayerHandle = {
|
|
1059
1103
|
/** Loads the KML and returns its node tree (recursing into container nodes). */
|
|
1060
1104
|
getNodes(): Promise<KmlNodeInfo[]>;
|
|
1105
|
+
/** Starts or resumes playback of the first KML tour found in the layer. No-ops if no tour exists. iOS only (see above). */
|
|
1106
|
+
playTour(): void;
|
|
1107
|
+
/** Pauses playback of the first KML tour found in the layer. No-ops if no tour exists. iOS only (see above). */
|
|
1108
|
+
pauseTour(): void;
|
|
1109
|
+
/** Resets playback of the first KML tour found in the layer to the beginning. No-ops if no tour exists. iOS only (see above). */
|
|
1110
|
+
resetTour(): void;
|
|
1061
1111
|
};
|
|
1062
1112
|
/**
|
|
1063
1113
|
* A geometry value. The `type` discriminator mirrors the ArcGIS web API
|
|
@@ -1343,6 +1393,32 @@ export type RouteTrackerHandle = {
|
|
|
1343
1393
|
trackLocation(location: TrackedLocation): Promise<RouteTrackingStatus>;
|
|
1344
1394
|
switchToNextDestination(): Promise<void>;
|
|
1345
1395
|
};
|
|
1396
|
+
/** Parameters for `serviceArea.solve`. */
|
|
1397
|
+
export type ServiceAreaSolveParams = {
|
|
1398
|
+
/** URL of the network analysis service (e.g. the ArcGIS World Service Areas service). */
|
|
1399
|
+
serviceUrl: string;
|
|
1400
|
+
/** Facility locations to compute service areas from. */
|
|
1401
|
+
facilities: PointGeometry[];
|
|
1402
|
+
/**
|
|
1403
|
+
* Impedance cutoff values (e.g. travel-time minutes or distance) that define each polygon ring.
|
|
1404
|
+
* When omitted the service's default cutoffs are used.
|
|
1405
|
+
*/
|
|
1406
|
+
cutoffs?: number[];
|
|
1407
|
+
};
|
|
1408
|
+
/** One service-area polygon returned from `serviceArea.solve`. Mirrors the native `ServiceAreaPolygon`. */
|
|
1409
|
+
export type ServiceAreaPolygon = {
|
|
1410
|
+
/** The polygon geometry of the reachable area. */
|
|
1411
|
+
geometry: Geometry;
|
|
1412
|
+
/** Lower impedance bound for this polygon ring. */
|
|
1413
|
+
fromCutoff: number;
|
|
1414
|
+
/** Upper impedance bound for this polygon ring. */
|
|
1415
|
+
toCutoff: number;
|
|
1416
|
+
};
|
|
1417
|
+
/** Result of `serviceArea.solve`. */
|
|
1418
|
+
export type ServiceAreaResult = {
|
|
1419
|
+
/** All result polygons across all facilities, ordered by facility then cutoff. */
|
|
1420
|
+
polygons: ServiceAreaPolygon[];
|
|
1421
|
+
};
|
|
1346
1422
|
/** Props for `<AnalysisOverlay>` — a container for visual analyses, hosted by a `<SceneView>`. */
|
|
1347
1423
|
export type AnalysisOverlayProps = {
|
|
1348
1424
|
/** Whether the overlay's analyses are drawn. Defaults to `true`. */
|
|
@@ -1687,7 +1763,7 @@ export type OfflineTileResult = {
|
|
|
1687
1763
|
/** Result of `offline.estimateTileCacheSize` — an estimate of the download footprint. */
|
|
1688
1764
|
export type TileCacheSizeEstimate = {
|
|
1689
1765
|
/** Estimated on-disk size of the tile cache in bytes. */
|
|
1690
|
-
|
|
1766
|
+
fileSizeBytes: number;
|
|
1691
1767
|
/** Estimated number of tiles in the tile cache. */
|
|
1692
1768
|
tileCount: number;
|
|
1693
1769
|
};
|
|
@@ -1818,6 +1894,27 @@ export type SimpleMarkerSceneSymbol = {
|
|
|
1818
1894
|
/** Which part of the solid sits on the point. Defaults to `bottom`. */
|
|
1819
1895
|
anchor?: 'center' | 'bottom' | 'top' | 'origin';
|
|
1820
1896
|
};
|
|
1897
|
+
/**
|
|
1898
|
+
* A 3D model symbol (glTF / `.glb`) for point graphics in a `<SceneView>`. Mirrors the native
|
|
1899
|
+
* `ModelSceneSymbol` (loads the model at `url` at runtime — symbol is `Loadable`).
|
|
1900
|
+
*/
|
|
1901
|
+
export type ModelSceneSymbol = {
|
|
1902
|
+
type: 'model-scene';
|
|
1903
|
+
/** URL of the glTF / `.glb` model file. Required. */
|
|
1904
|
+
url: string;
|
|
1905
|
+
/** Uniform scale factor applied to the model. Defaults to `1`. */
|
|
1906
|
+
scale?: number;
|
|
1907
|
+
/** Whether the model dimensions are expressed in device-independent pixels or geographic meters. Defaults to `dips`. */
|
|
1908
|
+
sizeUnits?: 'dips' | 'meters';
|
|
1909
|
+
/** Rotation around the vertical (z) axis, in degrees. Defaults to `0`. */
|
|
1910
|
+
heading?: number;
|
|
1911
|
+
/** Rotation around the lateral (x) axis, in degrees. Defaults to `0`. */
|
|
1912
|
+
pitch?: number;
|
|
1913
|
+
/** Rotation around the longitudinal (y) axis, in degrees. Defaults to `0`. */
|
|
1914
|
+
roll?: number;
|
|
1915
|
+
/** Which part of the model sits on the point. Defaults to `bottom`. */
|
|
1916
|
+
anchor?: 'center' | 'bottom' | 'top' | 'origin';
|
|
1917
|
+
};
|
|
1821
1918
|
/** A marker drawn from an image at a URL. Mirrors `PictureMarkerSymbol`. */
|
|
1822
1919
|
export type PictureMarkerSymbol = {
|
|
1823
1920
|
type: 'picture-marker';
|
|
@@ -1982,7 +2079,7 @@ export type MultilayerPointSymbolType = {
|
|
|
1982
2079
|
symbolLayers: SymbolLayerSpec[];
|
|
1983
2080
|
};
|
|
1984
2081
|
/** Any symbol usable by a `<Graphic>`. Mirrors the native `Symbol` hierarchy. */
|
|
1985
|
-
export type Symbol = SimpleMarkerSymbol | SimpleLineSymbol | SimpleFillSymbol | TextSymbol | SimpleMarkerSceneSymbol | PictureMarkerSymbol | PictureFillSymbol | DistanceCompositeSceneSymbol | CompositeSymbolType | MultilayerPointSymbolType;
|
|
2082
|
+
export type Symbol = SimpleMarkerSymbol | SimpleLineSymbol | SimpleFillSymbol | TextSymbol | SimpleMarkerSceneSymbol | ModelSceneSymbol | PictureMarkerSymbol | PictureFillSymbol | DistanceCompositeSceneSymbol | CompositeSymbolType | MultilayerPointSymbolType;
|
|
1986
2083
|
/** One stop in a `SizeVisualVariable` stops array. */
|
|
1987
2084
|
export type SizeStop = {
|
|
1988
2085
|
value: number;
|
|
@@ -2228,6 +2325,15 @@ export type SceneViewProps = {
|
|
|
2228
2325
|
atmosphereEffect?: AtmosphereEffect;
|
|
2229
2326
|
/** Sun position, as epoch milliseconds (affects shadow direction). */
|
|
2230
2327
|
sunTime?: number;
|
|
2328
|
+
/**
|
|
2329
|
+
* Filters time-aware layers to this time window. Both values are epoch milliseconds (UTC).
|
|
2330
|
+
* Pass `null` / omit to show all time steps (no filter). Maps to `GeoView.timeExtent` /
|
|
2331
|
+
* `SceneView(timeExtent:)` on both platforms.
|
|
2332
|
+
*/
|
|
2333
|
+
timeExtent?: {
|
|
2334
|
+
startTime: number;
|
|
2335
|
+
endTime: number;
|
|
2336
|
+
} | null;
|
|
2231
2337
|
/** Called once the scene has finished loading successfully. */
|
|
2232
2338
|
onSceneLoaded?: (event: {
|
|
2233
2339
|
nativeEvent: MapLoadedEventPayload;
|