diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSource.kt index cbb90de1fa..63df8e4914 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSource.kt @@ -5,20 +5,35 @@ import com.mapbox.maps.extension.style.sources.generated.RasterSource class RNMBXRasterSource(context: Context?) : RNMBXTileSource(context) { private var mTileSize: Int? = null + private var mPrefetchZoomDelta: Long? = null + private var mTileNetworkRequestsDelay: Double? = null override fun makeSource(): RasterSource { val id = iD!! val configurationUrl = uRL val tileSize = if (mTileSize == null) DEFAULT_TILE_SIZE else mTileSize!! - return if (configurationUrl != null) { - RasterSource.Builder(id).url(configurationUrl).tileSize(tileSize.toLong()).build() - } else RasterSource.Builder(id).tileSet(buildTileset()) - .tileSize(tileSize.toLong()).build() + val builder = if (configurationUrl != null) { + RasterSource.Builder(id).url(configurationUrl) + } else { + RasterSource.Builder(id).tileSet(buildTileset()) + } + builder.tileSize(tileSize.toLong()) + mPrefetchZoomDelta?.let { builder.prefetchZoomDelta(it) } + mTileNetworkRequestsDelay?.let { builder.tileNetworkRequestsDelay(it) } + return builder.build() } fun setTileSize(tileSize: Int) { mTileSize = tileSize } + fun setPrefetchZoomDelta(value: Long) { + mPrefetchZoomDelta = value + } + + fun setTileNetworkRequestsDelay(value: Double) { + mTileNetworkRequestsDelay = value + } + override fun hasPressListener(): Boolean { return false } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSourceManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSourceManager.kt index aa625b3c60..e6437d558e 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSourceManager.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterSourceManager.kt @@ -35,6 +35,16 @@ class RNMBXRasterSourceManager(reactApplicationContext: ReactApplicationContext) source.setTileSize(tileSize.asInt()) } + @ReactProp(name = "prefetchZoomDelta") + override fun setPrefetchZoomDelta(source: RNMBXRasterSource, value: Dynamic) { + source.setPrefetchZoomDelta(value.asInt().toLong()) + } + + @ReactProp(name = "tileNetworkRequestsDelay") + override fun setTileNetworkRequestsDelay(source: RNMBXRasterSource, value: Dynamic) { + source.setTileNetworkRequestsDelay(value.asDouble()) + } + override fun customEvents(): Map? { return eventMapOf( EventKeys.RASTER_SOURCE_LAYER_CLICK to "onMapboxRasterSourcePress", diff --git a/docs/RasterSource.md b/docs/RasterSource.md index ae7a2f5395..e62b7aa967 100644 --- a/docs/RasterSource.md +++ b/docs/RasterSource.md @@ -85,6 +85,28 @@ Mapbox urls default to 256, all others default to 512. +### prefetchZoomDelta + +```tsx +number +``` +When a tile for the current zoom level is not loaded yet, tiles up to this many zoom levels +above it are requested and rendered in its place. 0 turns this off, so only tiles for the +current zoom level are requested. The default value for this option is 4. + +[Raster Source tile requests](../examples/FillRasterLayer/RasterSourceTileRequests) + +### tileNetworkRequestsDelay + +```tsx +number +``` +Delay in milliseconds before a tile's network request is sent while a gesture or a camera +animation is in progress. Tiles that leave the viewport before the delay elapses are never +requested. Has no effect on an idle map. The default value for this option is 0. + +[Raster Source tile requests](../examples/FillRasterLayer/RasterSourceTileRequests) + ### tms ```tsx diff --git a/docs/docs.json b/docs/docs.json index d53b39f2f5..7c455bc769 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -7609,6 +7609,20 @@ "default": "none", "description": "Size of the map tiles.\nMapbox urls default to 256, all others default to 512." }, + { + "name": "prefetchZoomDelta", + "required": false, + "type": "number", + "default": "none", + "description": "When a tile for the current zoom level is not loaded yet, tiles up to this many zoom levels\nabove it are requested and rendered in its place. 0 turns this off, so only tiles for the\ncurrent zoom level are requested. The default value for this option is 4." + }, + { + "name": "tileNetworkRequestsDelay", + "required": false, + "type": "number", + "default": "none", + "description": "Delay in milliseconds before a tile's network request is sent while a gesture or a camera\nanimation is in progress. Tiles that leave the viewport before the delay elapses are never\nrequested. Has no effect on an idle map. The default value for this option is 0." + }, { "name": "tms", "required": false, diff --git a/docs/examples.json b/docs/examples.json index a9e67ad08c..d1d1b48ff1 100644 --- a/docs/examples.json +++ b/docs/examples.json @@ -866,6 +866,20 @@ "relPath": "FillRasterLayer/RasterSource.js", "name": "RasterSource" }, + { + "metadata": { + "title": "Raster Source tile requests", + "tags": [ + "RasterSource", + "RasterSource#prefetchZoomDelta", + "RasterSource#tileNetworkRequestsDelay" + ], + "docs": "\nFetches only the tiles of the current zoom level (no parent tiles as a placeholder) and waits 200 ms\nbefore requesting tiles while the map pans, so tiles that leave the screen during a fast pan are\nnever requested. Watch the network log while panning to compare with the Raster Source example.\n" + }, + "fullPath": "example/src/examples/FillRasterLayer/RasterSourceTileRequests.js", + "relPath": "FillRasterLayer/RasterSourceTileRequests.js", + "name": "RasterSourceTileRequests" + }, { "metadata": { "title": "Watercolor Raster Tiles", diff --git a/example/src/examples/FillRasterLayer/RasterSourceTileRequests.js b/example/src/examples/FillRasterLayer/RasterSourceTileRequests.js new file mode 100644 index 0000000000..befb15c4fc --- /dev/null +++ b/example/src/examples/FillRasterLayer/RasterSourceTileRequests.js @@ -0,0 +1,52 @@ +import React from 'react'; +import { MapView, RasterLayer, RasterSource, Camera } from '@rnmapbox/maps'; + +const styles = { + matchParent: { flex: 1 }, +}; + +export default function RasterSourceTileRequestsExample() { + return ( + + + + + + ); +} + +/* end-example-doc */ + +/** + * @typedef {import('../common/ExampleMetadata').ExampleWithMetadata} ExampleWithMetadata + * @type {ExampleWithMetadata['metadata']} + */ +const metadata = { + title: 'Raster Source tile requests', + tags: [ + 'RasterSource', + 'RasterSource#prefetchZoomDelta', + 'RasterSource#tileNetworkRequestsDelay', + ], + docs: ` +Fetches only the tiles of the current zoom level (no parent tiles as a placeholder) and waits 200 ms +before requesting tiles while the map pans, so tiles that leave the screen during a fast pan are +never requested. Watch the network log while panning to compare with the Raster Source example. +`, +}; +RasterSourceTileRequestsExample.metadata = metadata; diff --git a/example/src/examples/FillRasterLayer/index.js b/example/src/examples/FillRasterLayer/index.js index f9f81e4af9..28926e7962 100644 --- a/example/src/examples/FillRasterLayer/index.js +++ b/example/src/examples/FillRasterLayer/index.js @@ -7,6 +7,7 @@ export { default as QueryAtPoint } from './QueryAtPoint'; export { default as QuerySourceFeatures } from './QuerySourceFeatures'; export { default as QueryWithRect } from './QueryWithRect'; export { default as RasterSource } from './RasterSource'; +export { default as RasterSourceTileRequests } from './RasterSourceTileRequests'; export { default as WatercolorRasterTiles } from './WatercolorRasterTiles'; export { default as HillshadeSource } from './HillshadeSource'; diff --git a/ios/RNMBX/RNMBXRasterSource.swift b/ios/RNMBX/RNMBXRasterSource.swift index b883952410..0d2b5c1d02 100644 --- a/ios/RNMBX/RNMBXRasterSource.swift +++ b/ios/RNMBX/RNMBXRasterSource.swift @@ -11,6 +11,8 @@ public class RNMBXRasterSource : RNMBXSource { @objc public var minZoomLevel: NSNumber? @objc public var maxZoomLevel: NSNumber? @objc public var tileSize: NSNumber? + @objc public var prefetchZoomDelta: NSNumber? + @objc public var tileNetworkRequestsDelay: NSNumber? @objc public var tms: Bool = false @@ -31,6 +33,14 @@ public class RNMBXRasterSource : RNMBXSource { result.tileSize = tileSize.doubleValue } + if let prefetchZoomDelta = prefetchZoomDelta { + result.prefetchZoomDelta = prefetchZoomDelta.doubleValue + } + + if let tileNetworkRequestsDelay = tileNetworkRequestsDelay { + result.tileNetworkRequestsDelay = tileNetworkRequestsDelay.doubleValue + } + if let minZoomLevel = minZoomLevel { result.minzoom = minZoomLevel.doubleValue } diff --git a/ios/RNMBX/RNMBXRasterSourceComponentView.mm b/ios/RNMBX/RNMBXRasterSourceComponentView.mm index d007a56f69..dbfc5de905 100644 --- a/ios/RNMBX/RNMBXRasterSourceComponentView.mm +++ b/ios/RNMBX/RNMBXRasterSourceComponentView.mm @@ -104,6 +104,14 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & if (tileSize != nil) { _view.tileSize = tileSize; } + id prefetchZoomDelta = RNMBXConvertFollyDynamicToId(newProps.prefetchZoomDelta); + if (prefetchZoomDelta != nil) { + _view.prefetchZoomDelta = prefetchZoomDelta; + } + id tileNetworkRequestsDelay = RNMBXConvertFollyDynamicToId(newProps.tileNetworkRequestsDelay); + if (tileNetworkRequestsDelay != nil) { + _view.tileNetworkRequestsDelay = tileNetworkRequestsDelay; + } id tms = RNMBXConvertFollyDynamicToId(newProps.tms); if (tms != nil) { _view.tms = tms; diff --git a/src/components/RasterSource.tsx b/src/components/RasterSource.tsx index 7811f0c720..b6c41fca74 100644 --- a/src/components/RasterSource.tsx +++ b/src/components/RasterSource.tsx @@ -55,6 +55,20 @@ type Props = BaseProps & { */ tileSize?: number; + /** + * When a tile for the current zoom level is not loaded yet, tiles up to this many zoom levels + * above it are requested and rendered in its place. 0 turns this off, so only tiles for the + * current zoom level are requested. The default value for this option is 4. + */ + prefetchZoomDelta?: number; + + /** + * Delay in milliseconds before a tile's network request is sent while a gesture or a camera + * animation is in progress. Tiles that leave the viewport before the delay elapses are never + * requested. Has no effect on an idle map. The default value for this option is 0. + */ + tileNetworkRequestsDelay?: number; + /** * Influences the y direction of the tile coordinates. (tms inverts y axis) */ @@ -116,6 +130,8 @@ class RasterSource extends AbstractSource { minZoomLevel: this.props.minZoomLevel, maxZoomLevel: this.props.maxZoomLevel, tileSize: this.props.tileSize, + prefetchZoomDelta: this.props.prefetchZoomDelta, + tileNetworkRequestsDelay: this.props.tileNetworkRequestsDelay, tms: this.props.tms, attribution: this.props.attribution, }; diff --git a/src/specs/RNMBXRasterSourceNativeComponent.ts b/src/specs/RNMBXRasterSourceNativeComponent.ts index 8c22fea062..e5f4a5bf97 100644 --- a/src/specs/RNMBXRasterSourceNativeComponent.ts +++ b/src/specs/RNMBXRasterSourceNativeComponent.ts @@ -13,6 +13,8 @@ export interface NativeProps extends ViewProps { minZoomLevel: UnsafeMixed; maxZoomLevel: UnsafeMixed; tileSize: UnsafeMixed; + prefetchZoomDelta: UnsafeMixed; + tileNetworkRequestsDelay: UnsafeMixed; tms: UnsafeMixed; attribution: UnsafeMixed; sourceBounds: UnsafeMixed>;