Skip to content
Open
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
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ export default MyMap;
* [`enableClustering(...)`](#enableclustering)
* [`disableClustering()`](#disableclustering)
* [`addMarker(...)`](#addmarker)
* [`animateMarker(...)`](#animatemarker)
* [`addMarkers(...)`](#addmarkers)
* [`removeMarker(...)`](#removemarker)
* [`removeMarkers(...)`](#removemarkers)
Expand Down Expand Up @@ -416,6 +417,20 @@ addMarker(marker: Marker) => Promise<string>

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

### animateMarker(...)

```typescript
animateMarker(markerId: string, lat: number, lng: number, duration?: number | undefined) => Promise<void>
```

| Param | Type |
| -------------- | ------------------- |
| **`markerId`** | <code>string</code> |
| **`lat`** | <code>number</code> |
| **`lng`** | <code>number</code> |
| **`duration`** | <code>number</code> |

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

### addMarkers(...)

Expand Down
17 changes: 17 additions & 0 deletions plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ export default MyMap;
* [`enableClustering(...)`](#enableclustering)
* [`disableClustering()`](#disableclustering)
* [`addMarker(...)`](#addmarker)
* [`animateMarker(...)`](#animatemarker)
* [`addMarkers(...)`](#addmarkers)
* [`removeMarker(...)`](#removemarker)
* [`removeMarkers(...)`](#removemarkers)
Expand Down Expand Up @@ -417,6 +418,22 @@ addMarker(marker: Marker) => Promise<string>
--------------------


### animateMarker(...)

```typescript
animateMarker(markerId: string, lat: number, lng: number, duration?: number | undefined) => Promise<void>
```

| Param | Type |
| -------------- | ------------------- |
| **`markerId`** | <code>string</code> |
| **`lat`** | <code>number</code> |
| **`lng`** | <code>number</code> |
| **`duration`** | <code>number</code> |

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


### addMarkers(...)

```typescript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import java.io.InputStream
import java.net.URL
import android.animation.ValueAnimator
import android.animation.AnimatorListenerAdapter
import android.animation.Animator
import com.google.android.gms.maps.model.LatLng
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


class CapacitorGoogleMap(
Expand Down Expand Up @@ -244,6 +251,47 @@ class CapacitorGoogleMap(
}
}

fun animateMarker(markerId: String,lat: Double,lng: Double,duration: Long, callback: (Result<Unit>) -> Unit
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing spaces after commas in the parameter list. Should have spaces after 'String,', 'Double,', 'Double,', and 'Long,'.

Suggested change
fun animateMarker(markerId: String,lat: Double,lng: Double,duration: Long, callback: (Result<Unit>) -> Unit
fun animateMarker(markerId: String, lat: Double, lng: Double, duration: Long, callback: (Result<Unit>) -> Unit

Copilot uses AI. Check for mistakes.
) {
try {
googleMap ?: throw GoogleMapNotAvailable()

CoroutineScope(Dispatchers.Main).launch {
try {
val wrapper = markers[markerId] ?: throw MarkerNotFoundError()
val marker = wrapper.googleMapMarker
?: throw GoogleMapsError("GoogleMap Marker not available")

val startPos = marker.position
val endPos = LatLng(lat, lng)

ValueAnimator.ofFloat(0f, 1f).apply {
this.duration = duration
addUpdateListener { anim ->
val fraction = anim.animatedValue as Float
val newLat = startPos.latitude +
fraction * (endPos.latitude - startPos.latitude)
val newLng = startPos.longitude +
fraction * (endPos.longitude - startPos.longitude)
marker.position = LatLng(newLat, newLng)
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
callback(Result.success(Unit))
}
Comment on lines +271 to +281
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation is inconsistent in the animation block. Lines should be properly aligned within the ValueAnimator block.

Suggested change
val fraction = anim.animatedValue as Float
val newLat = startPos.latitude +
fraction * (endPos.latitude - startPos.latitude)
val newLng = startPos.longitude +
fraction * (endPos.longitude - startPos.longitude)
marker.position = LatLng(newLat, newLng)
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
callback(Result.success(Unit))
}
val fraction = anim.animatedValue as Float
val newLat = startPos.latitude +
fraction * (endPos.latitude - startPos.latitude)
val newLng = startPos.longitude +
fraction * (endPos.longitude - startPos.longitude)
marker.position = LatLng(newLat, newLng)
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
callback(Result.success(Unit))
}

Copilot uses AI. Check for mistakes.
})
}.start()
} catch (e: GoogleMapsError) {
callback(Result.failure(e))
} catch (e: Exception) {
callback(Result.failure(GoogleMapsError(e.localizedMessage ?: "Animation error")))
}
}
} catch (e: GoogleMapsError) {
callback(Result.failure(e))
}
}

fun addPolygons(newPolygons: List<CapacitorGoogleMapsPolygon>, callback: (ids: Result<List<String>>) -> Unit) {
try {
googleMap ?: throw GoogleMapNotAvailable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,40 @@ class CapacitorGoogleMapsPlugin : Plugin(), OnMapsSdkInitializedCallback {
}
}

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

val markerId = call.getString("markerId")
markerId ?: throw InvalidArgumentsError("markerId is missing")

val lat = call.getDouble("lat")
val lng = call.getDouble("lng")
if (lat == null || lng == null) {
throw InvalidArgumentsError("lat or lng is missing")
}
val duration = call.getLong("duration", 1000L)

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

map.animateMarker(markerId, lat, lng, duration) { result ->
result
.onSuccess {
call.resolve()
}
.onFailure { error ->
handleError(call, error)
}
}
} catch (e: GoogleMapsError) {
handleError(call, e)
} catch (e: Exception) {
handleError(call, e)
}
}

@PluginMethod
fun addMarkers(call: PluginCall) {
try {
Expand Down
1 change: 1 addition & 0 deletions plugin/ios/Plugin/CapacitorGoogleMapsPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
CAP_PLUGIN_METHOD(enableTouch, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(disableTouch, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(addMarker, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(animateMarker, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(addMarkers, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(addPolygons, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(addPolylines, CAPPluginReturnPromise);
Expand Down
31 changes: 31 additions & 0 deletions plugin/ios/Plugin/CapacitorGoogleMapsPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation
import Capacitor
import GoogleMaps
import GoogleMapsUtils
import QuartzCore

extension GMSMapViewType {
static func fromString(mapType: String) -> GMSMapViewType {
Expand Down Expand Up @@ -208,6 +209,36 @@ public class CapacitorGoogleMapsPlugin: CAPPlugin, GMSMapViewDelegate {
}
}

@objc func animateMarker(_ call: CAPPluginCall) {
do {
guard let id = call.getString("id") else {
throw GoogleMapErrors.invalidMapId
}
guard let markerId = call.getInt("markerId") else {
throw GoogleMapErrors.invalidArguments("markerId is missing")
}
guard let lat = call.getDouble("lat"),
let lng = call.getDouble("lng") else {
throw GoogleMapErrors.invalidArguments("lat or lng is missing")
}
let duration = call.getDouble("duration") ?? 1.0

guard let map = self.maps[id] else {
throw GoogleMapErrors.mapNotFound
}

try map.animateMarker(
markerId: markerId,
to: LatLng(lat: lat, lng: lng),
duration: duration
)

call.resolve()
} catch {
handleError(call, error: error)
}
}

@objc func addMarkers(_ call: CAPPluginCall) {
do {
guard let id = call.getString("id") else {
Expand Down
16 changes: 16 additions & 0 deletions plugin/ios/Plugin/Map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation
import GoogleMaps
import Capacitor
import GoogleMapsUtils
import QuartzCore

public struct LatLng: Codable {
let lat: Double
Expand Down Expand Up @@ -240,6 +241,21 @@ public class Map {
return markerHash
}

func animateMarker( markerId: Int, to target: LatLng, duration: Double) throws {
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space after opening parenthesis. Should be 'func animateMarker(markerId: Int, to target: LatLng, duration: Double) throws {'.

Suggested change
func animateMarker( markerId: Int, to target: LatLng, duration: Double) throws {
func animateMarker(markerId: Int, to target: LatLng, duration: Double) throws {

Copilot uses AI. Check for mistakes.
guard let marker = markers[markerId] else {
throw GoogleMapErrors.markerNotFound
}
DispatchQueue.main.async {
CATransaction.begin()
CATransaction.setAnimationDuration(duration)
marker.position = CLLocationCoordinate2D(
latitude: target.lat,
longitude: target.lng
)
CATransaction.commit()
}
}

func addMarkers(markers: [Marker]) throws -> [Int] {
var markerHashes: [Int] = []

Expand Down
8 changes: 8 additions & 0 deletions plugin/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,14 @@ export interface Marker {
zIndex?: number;
}

export interface AnimateMarkerOptions {
id: string;
markerId: string;
lat: number;
lng: number;
duration?: number;
}

/**
* The callback function to be called when map events are emitted.
*/
Expand Down
10 changes: 10 additions & 0 deletions plugin/src/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Plugin } from '@capacitor/core';
import { registerPlugin } from '@capacitor/core';

import type {
AnimateMarkerOptions,
CameraConfig,
Circle,
GoogleMapConfig,
Expand Down Expand Up @@ -73,6 +74,14 @@ export interface AddMarkerArgs {
marker: Marker;
}

export interface AnimateMarkerArgs {
id: string;
markerId: string;
lat: number;
lng: number;
duration?: number;
}

export interface AddPolygonsArgs {
id: string;
polygons: Polygon[];
Expand Down Expand Up @@ -174,6 +183,7 @@ export interface CapacitorGoogleMapsPlugin extends Plugin {
enableTouch(args: { id: string }): Promise<void>;
disableTouch(args: { id: string }): Promise<void>;
addMarker(args: AddMarkerArgs): Promise<{ id: string }>;
animateMarker(options: AnimateMarkerOptions): Promise<void>;
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface method uses 'AnimateMarkerOptions' but the implementation uses 'AnimateMarkerArgs'. This inconsistency could cause confusion and type mismatches.

Suggested change
animateMarker(options: AnimateMarkerOptions): Promise<void>;
animateMarker(options: AnimateMarkerArgs): Promise<void>;

Copilot uses AI. Check for mistakes.
addMarkers(args: AddMarkersArgs): Promise<{ ids: string[] }>;
removeMarker(args: RemoveMarkerArgs): Promise<void>;
removeMarkers(args: RemoveMarkersArgs): Promise<void>;
Expand Down
19 changes: 19 additions & 0 deletions plugin/src/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface GoogleMapInterface {
): Promise<void>;
disableClustering(): Promise<void>;
addMarker(marker: Marker): Promise<string>;
animateMarker(markerId: string,lat: number,lng: number,duration?: number): Promise<void>;
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing spaces after commas in the parameter list. Should be 'markerId: string, lat: number, lng: number, duration?: number'.

Suggested change
animateMarker(markerId: string,lat: number,lng: number,duration?: number): Promise<void>;
animateMarker(markerId: string, lat: number, lng: number, duration?: number): Promise<void>;

Copilot uses AI. Check for mistakes.
addMarkers(markers: Marker[]): Promise<string[]>;
removeMarker(id: string): Promise<void>;
removeMarkers(ids: string[]): Promise<void>;
Expand Down Expand Up @@ -348,6 +349,24 @@ export class GoogleMap {
return res.id;
}

/**
* Animation of marker
*/
async animateMarker(
markerId: string,
lat: number,
lng: number,
duration = 1000
): Promise<void> {
await CapacitorGoogleMaps.animateMarker({
id: this.id,
markerId,
lat,
lng,
duration,
});
}

/**
* Adds multiple markers to the map
*
Expand Down
31 changes: 31 additions & 0 deletions plugin/src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
RemoveCirclesArgs,
AddPolylinesArgs,
RemovePolylinesArgs,
AnimateMarkerArgs,
} from './implementation';

export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogleMapsPlugin {
Expand Down Expand Up @@ -291,6 +292,36 @@ export class CapacitorGoogleMapsWeb extends WebPlugin implements CapacitorGoogle

return { id: id };
}

async animateMarker(_args: AnimateMarkerArgs): Promise<void> {
const { id, markerId, lat, lng, duration = 1000 } = _args;
const mapData = this.maps[id];
if (!mapData) {
throw new Error(`Map with id '${id}' not found`);
}
const marker = mapData.markers[markerId];
if (!marker) {
throw new Error(`Marker '${markerId}' not found on map '${id}'`);
}
const start = marker.position as google.maps.LatLngLiteral;
const end = { lat, lng };
const startTime = performance.now();

return new Promise<void>(resolve => {
const step = (now: number) => {
const t = Math.min((now - startTime) / duration, 1);
const currLat = start.lat + (end.lat - start.lat) * t;
const currLng = start.lng + (end.lng - start.lng) * t;
marker.position = { lat: currLat, lng: currLng };
if (t < 1) {
requestAnimationFrame(step);
} else {
resolve();
}
};
requestAnimationFrame(step);
});
}

async removeMarkers(_args: RemoveMarkersArgs): Promise<void> {
const map = this.maps[_args.id];
Expand Down