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
8 changes: 8 additions & 0 deletions android/src/main/java/com/luggmaps/LuggMapView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
private var maxZoom: Double? = null
private var edgeInsets: EdgeInsets = EdgeInsets()
private var insetAdjustment: String = "never"
private var idleFrameRate: String = "maximum"

// region View Lifecycle

Expand Down Expand Up @@ -214,6 +215,7 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
provider?.setPoiEnabled(poiEnabled)
provider?.setPoiFilterMode(poiFilterMode)
provider?.setPoiFilterCategories(poiFilterCategories)
provider?.setIdleFrameRate(idleFrameRate)
}

fun setProvider(value: String?) {
Expand Down Expand Up @@ -330,6 +332,12 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
provider?.setInsetAdjustment(value)
}

fun setIdleFrameRate(value: String) {
if (idleFrameRate == value) return
idleFrameRate = value
provider?.setIdleFrameRate(value)
}

fun setEdgeInsets(
top: Int,
left: Int,
Expand Down
5 changes: 5 additions & 0 deletions android/src/main/java/com/luggmaps/LuggMapViewManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ class LuggMapViewManager :
view.setInsetAdjustment(value ?: "never")
}

@ReactProp(name = "idleFrameRate")
override fun setIdleFrameRate(view: LuggMapView, value: String?) {
view.setIdleFrameRate(value ?: "maximum")
}

@ReactProp(name = "edgeInsets")
override fun setEdgeInsets(view: LuggMapView, value: ReadableMap?) {
value?.let {
Expand Down
87 changes: 86 additions & 1 deletion android/src/main/java/com/luggmaps/LuggMarkerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {

var isDragging: Boolean = false

private var pathLatitudes = DoubleArray(0)
private var pathLongitudes = DoubleArray(0)
private var pathTimes = DoubleArray(0)
private var pathRotations = DoubleArray(0)
private var pathStartTime = 0.0
private var pathLoop = false

// The path position at the last updatePathPosition
var pathLatitude: Double = 0.0
private set
var pathLongitude: Double = 0.0
private set
var pathRotation: Float = 0f
private set

val hasPath: Boolean
get() = pathTimes.size >= 2 && pathTimes.size == pathLatitudes.size

// A path overrides coordinate, and rotate when the path has rotations
val displayLatitude: Double
get() = if (hasPath) pathLatitude else latitude
val displayLongitude: Double
get() = if (hasPath) pathLongitude else longitude
val displayRotation: Float
get() = if (hasPath) pathRotation else rotate

var didLayout: Boolean = false
private set

Expand Down Expand Up @@ -290,8 +316,67 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
this.draggable = draggable
}

fun setPathCoordinates(latitudes: DoubleArray, longitudes: DoubleArray) {
pathLatitudes = latitudes
pathLongitudes = longitudes
}

fun setPathTimes(times: DoubleArray) {
pathTimes = times
}

// Unwrapped so each segment turns the short way (350 then 10 is +20, not -340)
fun setPathRotations(rotations: DoubleArray) {
pathRotations = rotations.copyOf()
for (i in 1 until pathRotations.size) {
val previous = pathRotations[i - 1]
pathRotations[i] = previous + ((((rotations[i] - previous) % 360) + 540) % 360) - 180
}
}

fun setPathStartTime(startTime: Double) {
pathStartTime = startTime
}

fun setPathLoop(loop: Boolean) {
pathLoop = loop
}

// `now` is wall-clock epoch ms, the same clock as pathStartTime
fun updatePathPosition(now: Double) {
if (!hasPath) return
val times = pathTimes
val last = times.size - 1
val duration = times[last] - times[0]
val elapsed = now - pathStartTime
val phase = if (pathLoop && duration > 0) {
((elapsed % duration) + duration) % duration
} else {
// Not coerceIn: it throws when unsorted times make the duration negative
maxOf(0.0, minOf(elapsed, duration))
}
val time = times[0] + phase

var index = 0
var high = last - 1
while (index < high) {
val mid = (index + high + 1) ushr 1
if (times[mid] <= time) index = mid else high = mid - 1
}
val span = times[index + 1] - times[index]
val fraction = if (span > 0) (time - times[index]) / span else 0.0

pathLatitude = pathLatitudes[index] + (pathLatitudes[index + 1] - pathLatitudes[index]) * fraction
pathLongitude = pathLongitudes[index] + (pathLongitudes[index + 1] - pathLongitudes[index]) * fraction
pathRotation = if (pathRotations.size == times.size) {
(pathRotations[index] + (pathRotations[index + 1] - pathRotations[index]) * fraction).toFloat()
} else {
rotate
}
}

fun emitPressEvent(x: Float, y: Float) {
dispatchEvent(MarkerPressEvent(this, latitude, longitude, x, y))
dispatchEvent(MarkerPressEvent(this, displayLatitude, displayLongitude, x, y))
}

fun emitDragStartEvent(x: Float, y: Float) {
Expand Down
39 changes: 39 additions & 0 deletions android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.luggmaps

import android.util.Log
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
Expand Down Expand Up @@ -102,6 +103,44 @@ class LuggMarkerViewManager :
view.setDraggable(value)
}

@ReactProp(name = "pathCoordinates")
override fun setPathCoordinates(view: LuggMarkerView, value: ReadableArray?) {
val size = value?.size() ?: 0
val latitudes = DoubleArray(size)
val longitudes = DoubleArray(size)
for (i in 0 until size) {
val coordinate = value?.getMap(i)
latitudes[i] = coordinate?.getDouble("latitude") ?: 0.0
longitudes[i] = coordinate?.getDouble("longitude") ?: 0.0
}
view.setPathCoordinates(latitudes, longitudes)
}

@ReactProp(name = "pathTimes")
override fun setPathTimes(view: LuggMarkerView, value: ReadableArray?) {
view.setPathTimes(value.toDoubleArray())
}

@ReactProp(name = "pathRotations")
override fun setPathRotations(view: LuggMarkerView, value: ReadableArray?) {
view.setPathRotations(value.toDoubleArray())
}

@ReactProp(name = "pathStartTime")
override fun setPathStartTime(view: LuggMarkerView, value: Double) {
view.setPathStartTime(value)
}

@ReactProp(name = "pathLoop", defaultBoolean = false)
override fun setPathLoop(view: LuggMarkerView, value: Boolean) {
view.setPathLoop(value)
}

private fun ReadableArray?.toDoubleArray(): DoubleArray {
val array = this ?: return DoubleArray(0)
return DoubleArray(array.size()) { array.getDouble(it) }
}

override fun showCallout(view: LuggMarkerView) {
view.showCallout()
}
Expand Down
Loading
Loading