Skip to content

Commit

Permalink
Adds Custom Tile Overlay Feature
Browse files Browse the repository at this point in the history
  • Loading branch information
FlossyWeb committed Oct 30, 2024
1 parent 3281142 commit 8f4f9a2
Show file tree
Hide file tree
Showing 25 changed files with 597 additions and 353 deletions.
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"node": ">=20",
"pnpm": ">=8"
},
"dependencies": {},
"workspaces": [
"plugin"
]
],
"packageManager": "[email protected]+sha1.4fb96925d434c491285182acf29803bb9aa2e6e5"
}
28 changes: 28 additions & 0 deletions plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export default MyMap;
* [`disableTouch()`](#disabletouch)
* [`enableClustering(...)`](#enableclustering)
* [`disableClustering()`](#disableclustering)
* [`addTileOverlay(...)`](#addtileoverlay)
* [`addMarker(...)`](#addmarker)
* [`addMarkers(...)`](#addmarkers)
* [`removeMarker(...)`](#removemarker)
Expand Down Expand Up @@ -402,6 +403,19 @@ disableClustering() => Promise<void>
--------------------


### addTileOverlay(...)

```typescript
addTileOverlay(tiles: TileOverlay) => Promise<void>
```

| Param | Type |
| ----------- | --------------------------------------------------- |
| **`tiles`** | <code><a href="#tileoverlay">TileOverlay</a></code> |

--------------------


### addMarker(...)

```typescript
Expand Down Expand Up @@ -949,6 +963,20 @@ An interface representing a pair of latitude and longitude coordinates.
| **`mapId`** | <code>string</code> |


#### TileOverlay

For web, all the javascript <a href="#tileoverlay">TileOverlay</a> options are available as
For iOS and Android only the config options declared on <a href="#tileoverlay">TileOverlay</a> are available.

| Prop | Type |
| ------------- | -------------------------------------------------------------- |
| **`getTile`** | <code>(x: number, y: number, zoom: number) =&gt; string</code> |
| **`opacity`** | <code>number</code> |
| **`visible`** | <code>boolean</code> |
| **`zIndex`** | <code>number</code> |
| **`debug`** | <code>boolean</code> |


#### Marker

A marker is an icon placed at a particular point on the map's surface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.google.maps.android.clustering.ClusterManager
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL


Expand All @@ -45,7 +46,7 @@ class CapacitorGoogleMap(
private val markers = HashMap<String, CapacitorGoogleMapMarker>()
private val polygons = HashMap<String, CapacitorGoogleMapsPolygon>()
private val circles = HashMap<String, CapacitorGoogleMapsCircle>()
private val polylines = HashMap<String, CapacitorGoogleMapPolyline>()
private val polylines = HashMap<String, CapacitorGoogleMapPolyline>()
private val markerIcons = HashMap<String, Bitmap>()
private var clusterManager: ClusterManager<CapacitorGoogleMapMarker>? = null

Expand Down Expand Up @@ -173,6 +174,82 @@ class CapacitorGoogleMap(
}
}

fun addTileOverlay(tileOverlay: CapacitorGoogleMapsTileOverlay, callback: (result: Result<String>) -> Unit) {
try {
googleMap ?: throw GoogleMapNotAvailable()
var tileOverlayId: String

val bitmapFunc = CoroutineScope(Dispatchers.IO).async {
val url = URL(tileOverlay.imageSrc)
val connection: HttpURLConnection = url.openConnection() as HttpURLConnection

connection.doInput = true
connection.connect()

val input: InputStream = connection.inputStream

BitmapFactory.decodeStream(input)
}

CoroutineScope(Dispatchers.Main).launch {
/*
var tileProvider: TileProvider = object : UrlTileProvider(256, 256) {
override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
/* Define the URL pattern for the tile images */
val url = "https://avatars.githubusercontent.com/u/103097039?v=4"
return if (!checkTileExists(x, y, zoom)) {
null
} else try {
URL(url)
} catch (e: MalformedURLException) {
throw AssertionError(e)
}
}
/*
* Check that the tile server supports the requested x, y and zoom.
* Complete this stub according to the tile range you support.
* If you support a limited range of tiles at different zoom levels, then you
* need to define the supported x, y range at each zoom level.
*/
private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean {
val minZoom = 1
val maxZoom = 16
return zoom in minZoom..maxZoom
}
}
Log.d("TileOverlay ^^^ ", "tileProvider")
val tileOverlay = googleMap?.addTileOverlay(
TileOverlayOptions()
.tileProvider(tileProvider)
)
*/

val bitmap = bitmapFunc.await()

// Now you can safely use the bitmap
if (bitmap != null) {
val imageDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap)

val groundOverlay = googleMap?.addGroundOverlay(
GroundOverlayOptions()
.image(imageDescriptor)
.positionFromBounds(tileOverlay.imageBounds)
.transparency(tileOverlay.opacity)
.zIndex(tileOverlay.zIndex)
.visible(tileOverlay.visible)
)

tileOverlay.googleMapsTileOverlay = groundOverlay
tileOverlayId = groundOverlay!!.id

callback(Result.success(tileOverlayId))
}
}
} catch (e: GoogleMapsError) {
callback(Result.failure(e))
}
}

fun addMarkers(
newMarkers: List<CapacitorGoogleMapMarker>,
callback: (ids: Result<List<String>>) -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,45 @@ class CapacitorGoogleMapsPlugin : Plugin(), OnMapsSdkInitializedCallback {
}
}

@PluginMethod
fun addTileOverlay(call: PluginCall) {
try {
val id = call.getString("id")
id ?: throw InvalidMapIdError()

val imageBoundsObj = call.getObject("imageBounds") ?: throw InvalidArgumentsError("imageBounds object is missing")

val imageSrc = call.getString("imageSrc")
val opacity = call.getFloat("opacity", 1.0f)
val zIndex = call.getFloat("zIndex", 0.0f)
val visible = call.getBoolean("visible", true)

val tileOverlayConfig = JSONObject()
tileOverlayConfig.put("imageBounds", imageBoundsObj)
tileOverlayConfig.put("imageSrc", imageSrc)
tileOverlayConfig.put("opacity", opacity)
tileOverlayConfig.put("zIndex", zIndex)
tileOverlayConfig.put("visible", visible)

val map = maps[id]
map ?: throw MapNotFoundError()

val tileOptions = CapacitorGoogleMapsTileOverlay(tileOverlayConfig)

map.addTileOverlay(tileOptions) { result ->
val tileOverlayId = result.getOrThrow()

val res = JSObject()
res.put("id", tileOverlayId)
call.resolve(res)
}
} catch (e: GoogleMapsError) {
handleError(call, e)
} catch (e: Exception) {
handleError(call, e)
}
}

@PluginMethod
fun addMarkers(call: PluginCall) {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.capacitorjs.plugins.googlemaps

import com.google.android.gms.maps.model.GroundOverlay
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import org.json.JSONObject

class CapacitorGoogleMapsTileOverlay(fromJSONObject: JSONObject) {
var imageBounds: LatLngBounds
var imageSrc: String? = null
var opacity: Float = 1.0f
var zIndex: Float = 0.0f
var visible: Boolean = true
var googleMapsTileOverlay: GroundOverlay? = null

init {
val latLngObj = fromJSONObject.getJSONObject("imageBounds")
val north = latLngObj.optDouble("north", 0.0)
val south = latLngObj.optDouble("south", 0.0)
val east = latLngObj.optDouble("east", 0.0)
val west = latLngObj.optDouble("west", 0.0)

imageBounds = LatLngBounds(LatLng(south, west), LatLng(north, east))
imageSrc = fromJSONObject.optString("imageSrc", null)
zIndex = fromJSONObject.optLong("zIndex", 0).toFloat()
visible = fromJSONObject.optBoolean("visible", true)
opacity = 1.0f - fromJSONObject.optDouble("opacity", 1.0).toFloat()
}
}
Loading

0 comments on commit 8f4f9a2

Please sign in to comment.