Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ React-native wrapper for android & IOS google maps sdk
yarn add react-native-google-maps-plus react-native-nitro-modules
```

Dependencies
# Dependencies

This package builds on native SVG rendering libraries:
This package builds on native libraries for SVG rendering and Google Maps integration:

iOS: [SVGKit](https://github.com/SVGKit/SVGKit)

Android: [AndroidSVG](https://bigbadaboom.github.io/androidsvg/)
- **iOS**: [SVGKit](https://github.com/SVGKit/SVGKit)
- **Android**: [AndroidSVG](https://bigbadaboom.github.io/androidsvg/)
- **iOS Maps SDK**: [Google Maps SDK for iOS](https://developers.google.com/maps/documentation/ios-sdk)
- **Android Maps SDK**: [Google Maps SDK for Android](https://developers.google.com/maps/documentation/android-sdk)
- **Maps Utility Libraries**: [Google Maps Utils for iOS](https://developers.google.com/maps/documentation/ios-sdk/utility) and [Google Maps Utils for Android](https://developers.google.com/maps/documentation/android-sdk/utility)

These are automatically linked when you install the package, but you may need to clean/rebuild your native projects after first install.

Expand Down
3 changes: 2 additions & 1 deletion RNGoogleMapsPlus.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ Pod::Spec.new do |s|
s.dependency 'React-jsi'
s.dependency 'React-callinvoker'

s.dependency 'GoogleMaps', '10.3.0'
s.dependency 'GoogleMaps', '10.4.0'
s.dependency 'Google-Maps-iOS-Utils', '6.1.3'
s.dependency 'SVGKit', '3.0.0'

load 'nitrogen/generated/ios/RNGoogleMapsPlus+autolinking.rb'
Expand Down
54 changes: 54 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import com.google.android.gms.maps.model.Polygon
import com.google.android.gms.maps.model.PolygonOptions
import com.google.android.gms.maps.model.Polyline
import com.google.android.gms.maps.model.PolylineOptions
import com.google.android.gms.maps.model.TileOverlay
import com.google.android.gms.maps.model.TileOverlayOptions
import com.rngooglemapsplus.extensions.toGooglePriority
import com.rngooglemapsplus.extensions.toLocationErrorCode

Expand Down Expand Up @@ -52,11 +54,13 @@ class GoogleMapsViewImpl(
private val pendingPolylines = mutableListOf<Pair<String, PolylineOptions>>()
private val pendingPolygons = mutableListOf<Pair<String, PolygonOptions>>()
private val pendingCircles = mutableListOf<Pair<String, CircleOptions>>()
private val pendingHeatmaps = mutableListOf<Pair<String, TileOverlayOptions>>()

private val markersById = mutableMapOf<String, Marker>()
private val polylinesById = mutableMapOf<String, Polyline>()
private val polygonsById = mutableMapOf<String, Polygon>()
private val circlesById = mutableMapOf<String, Circle>()
private val heatmapsById = mutableMapOf<String, TileOverlay>()

private var cameraMoveReason = -1
private var lastSubmittedLocation: Location? = null
Expand Down Expand Up @@ -332,6 +336,13 @@ class GoogleMapsViewImpl(
}
pendingCircles.clear()
}

if (pendingHeatmaps.isNotEmpty()) {
pendingHeatmaps.forEach { (id, opts) ->
internalAddHeatmap(id, opts)
}
pendingHeatmaps.clear()
}
}

var uiSettings: RNMapUiSettings? = null
Expand Down Expand Up @@ -772,13 +783,56 @@ class GoogleMapsViewImpl(
pendingCircles.clear()
}

fun addHeatmap(
id: String,
opts: TileOverlayOptions,
) {
if (googleMap == null) {
pendingHeatmaps.add(id to opts)
return
}

onUi {
heatmapsById.remove(id)?.remove()
}
internalAddHeatmap(id, opts)
}

private fun internalAddHeatmap(
id: String,
opts: TileOverlayOptions,
) {
onUi {
val heatmap =
googleMap?.addTileOverlay(opts)
if (heatmap != null) {
heatmapsById[id] = heatmap
}
}
}

fun removeHeatmap(id: String) {
onUi {
heatmapsById.remove(id)?.remove()
}
}

fun clearHeatmaps() {
onUi {
heatmapsById.values.forEach { it.remove() }
}
circlesById.clear()
pendingHeatmaps.clear()
}

fun destroyInternal() {
onUi {
markerBuilder.cancelAllJobs()
clearMarkers()
clearPolylines()
clearPolygons()
clearCircles()
clearHeatmaps()
locationHandler.stop()
googleMap?.apply {
setOnCameraMoveStartedListener(null)
Expand Down
31 changes: 31 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/MapHeatmapBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.rngooglemapsplus

import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.google.android.gms.maps.model.TileOverlayOptions
import com.google.maps.android.heatmaps.Gradient
import com.google.maps.android.heatmaps.HeatmapTileProvider
import com.rngooglemapsplus.extensions.toColor
import com.rngooglemapsplus.extensions.toWeightedLatLngs

class MapHeatmapBuilder {
fun build(heatmap: RNHeatmap): TileOverlayOptions {
val provider =
HeatmapTileProvider
.Builder()
.apply {
weightedData(heatmap.weightedData.toWeightedLatLngs())
heatmap.radius?.let { radius(it.dpToPx().toInt().coerceIn(10, 50)) }
heatmap.opacity?.let { opacity(it) }
heatmap.gradient?.let {
val colors = it.colors.map { c -> c.toColor() }.toIntArray()
val startPoints = it.startPoints.map { p -> p.toFloat() }.toFloatArray()
gradient(Gradient(colors, startPoints))
}
}.build()

return TileOverlayOptions().apply {
tileProvider(provider)
heatmap.zIndex?.let { zIndex(it.toFloat()) }
}
}
}
16 changes: 16 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class RNGoogleMapsPlusView(
private val polylineBuilder = MapPolylineBuilder()
private val polygonBuilder = MapPolygonBuilder()
private val circleBuilder = MapCircleBuilder()
private val heatmapBuilder = MapHeatmapBuilder()

override val view =
GoogleMapsViewImpl(context, locationHandler, playServiceHandler, markerBuilder)
Expand Down Expand Up @@ -218,6 +219,21 @@ class RNGoogleMapsPlusView(
}
}

override var heatmaps: Array<RNHeatmap>? = null
set(value) {
if (field.contentEquals(value)) return
val prevById = field?.associateBy { it.id } ?: emptyMap()
val nextById = value?.associateBy { it.id } ?: emptyMap()
field = value
(prevById.keys - nextById.keys).forEach { id ->
view.removeHeatmap(id)
}

nextById.forEach { (id, next) ->
view.addHeatmap(id, heatmapBuilder.build(next))
}
}

override var locationConfig: RNLocationConfig? = null
set(value) {
if (field == value) return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.rngooglemapsplus.extensions

import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.heatmaps.WeightedLatLng
import com.rngooglemapsplus.RNHeatmapPoint

fun RNHeatmapPoint.toWeightedLatLng(): WeightedLatLng = WeightedLatLng(LatLng(latitude, longitude), weight)

fun Array<RNHeatmapPoint>.toWeightedLatLngs(): Collection<WeightedLatLng> = map { it.toWeightedLatLng() }
17 changes: 11 additions & 6 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ PODS:
- FBLazyVector (0.82.0)
- fmt (11.0.2)
- glog (0.3.5)
- GoogleMaps (10.3.0):
- GoogleMaps/Maps (= 10.3.0)
- GoogleMaps/Maps (10.3.0)
- Google-Maps-iOS-Utils (6.1.3):
- GoogleMaps (~> 10.0)
- GoogleMaps (10.4.0):
- GoogleMaps/Maps (= 10.4.0)
- GoogleMaps/Maps (10.4.0)
- hermes-engine (0.82.0):
- hermes-engine/Pre-built (= 0.82.0)
- hermes-engine/Pre-built (0.82.0)
Expand Down Expand Up @@ -2362,7 +2364,8 @@ PODS:
- fast_float
- fmt
- glog
- GoogleMaps (= 10.3.0)
- Google-Maps-iOS-Utils (= 6.1.3)
- GoogleMaps (= 10.4.0)
- hermes-engine
- NitroModules
- RCT-Folly
Expand Down Expand Up @@ -2475,6 +2478,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- CocoaLumberjack
- Google-Maps-iOS-Utils
- GoogleMaps
- SocketRocket
- SVGKit
Expand Down Expand Up @@ -2640,7 +2644,8 @@ SPEC CHECKSUMS:
FBLazyVector: 41b4dd99afd0aad861444ee141abdedaa6c3d238
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
GoogleMaps: 197af8911284ddf36db063c74faee4c4ab15e9d9
Google-Maps-iOS-Utils: bed22fa703c919259b3901449434d60d994fae20
GoogleMaps: a40d3b1f511f0fa2036e7b08c920c33279b1d5fd
hermes-engine: 8642d8f14a548ab718ec112e9bebdfdd154138b5
NitroModules: 73c42f3089bd74f411172ea8e69024aac4a2ac9f
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
Expand Down Expand Up @@ -2708,7 +2713,7 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: c5c4f5280e4ae0f9f4a739c64c4260fe0b3edaf1
ReactCodegen: 3873d7ac09960375f7845384ff47d53e478462dc
ReactCommon: f5527f5d97a9957ab46eb5db78875d3579e03b97
RNGoogleMapsPlus: 4f8dd1f33c906f62e877f1aa65cd8ac5ec6b020b
RNGoogleMapsPlus: 9b638ea84ab0231430a8b5a109a20130ad4a722a
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
SVGKit: 1ad7513f8c74d9652f94ed64ddecda1a23864dea
Yoga: ce55ebb197c21e22b6700cd36e3f36b7ec26e6f8
Expand Down
37 changes: 37 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
RNRegion,
RNLatLng,
RNCircle,
RNHeatmap,
} from '../../src';
import { GoogleMapsView, GoogleMapsModule } from '../../src';
import { callback } from 'react-native-nitro-modules';
Expand Down Expand Up @@ -204,6 +205,16 @@ const randomCoordinates = (
longitude: baseLng + (Math.random() - 0.5) * offset,
});

const randomWeightedCoordinates = (
baseLat: number,
baseLng: number,
offset = 0.01
) => ({
latitude: baseLat + (Math.random() - 0.5) * offset,
longitude: baseLng + (Math.random() - 0.5) * offset,
weight: Math.floor(Math.random() * (100 - 10 + 1)) + 10,
});

const makePolygon = (id: number): RNPolygon => ({
id: id.toString(),
zIndex: id,
Expand Down Expand Up @@ -246,6 +257,27 @@ const makeCircle = (id: number): RNCircle => ({
fillColor: '#0000ff',
});

const makeHeatmap = (id: number): RNHeatmap => ({
id: id.toString(),
zIndex: id,
weightedData: [
randomWeightedCoordinates(37.7749, -122.4194, 0.02),
randomWeightedCoordinates(37.7749, -122.4194, 0.03),
randomWeightedCoordinates(37.7749, -122.4194, 0.05),
randomWeightedCoordinates(37.7749, -122.4194, 0.01),
randomWeightedCoordinates(37.7749, -122.4194, 0.08),
randomWeightedCoordinates(37.7749, -122.4194, 0.03),
randomWeightedCoordinates(37.7749, -122.4194, 0.09),
],
gradient: {
colors: ['#00f', '#0ff', '#0f0', '#ff0', '#f00'],
startPoints: [0.1, 0.3, 0.5, 0.7, 1],
colorMapSize: 256,
},
radius: 100,
opacity: 1,
});

export const makeMarker = (id: number): RNMarker => ({
id: id.toString(),
zIndex: id,
Expand Down Expand Up @@ -333,6 +365,10 @@ export default function App() {
Array.from({ length: 1 }, (_, i) => makeCircle(i + 1))
);

const [heatmaps] = useState(
Array.from({ length: 1 }, (_, i) => makeHeatmap(i + 1))
);

useEffect(() => {
if (!stressTest) return;

Expand Down Expand Up @@ -506,6 +542,7 @@ export default function App() {
polygons={polygons}
polylines={polylines}
circles={circles}
heatmaps={heatmaps}
/>

<ScrollView style={styles.scrollView}>
Expand Down
2 changes: 2 additions & 0 deletions ios/.swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ disabled_rules:
- file_length
- type_body_length
- cyclomatic_complexity
- function_body_length
- closure_parameter_position
- todo

identifier_name:
Expand Down
Loading
Loading