Clue Mediator

Move marker smoothly on Google Maps in React

๐Ÿ“…April 12, 2023
๐Ÿ—ReactJS

In Google Maps, markers are often used to indicate locations or points of interest on the map. But what if you want to move the marker from one location to another smoothly and dynamically?

This is where the animation capabilities of Google Maps come in handy. In this article, we will discuss how to move a marker smoothly on Google Maps in a React application using the `setTimeout` in the Google Maps API.

Demo Application

Output - Move marker smoothly on Google Maps in React - Clue Mediator

Output - Move marker smoothly on Google Maps in React - Clue Mediator

Move marker smoothly on Google Maps in React

  1. Project structure
  2. Package dependencies
  3. Implementation
  4. Output

1. Project structure

  • move-marker-google-maps-react

    • node_modules

    • public

      • index.html
    • src

      • App.js
      • GMap.js
      • index.css
      • index.js
    • package-lock.json

    • package.json

    • README.md

2. Package dependencies

Run the following command to install @googlemaps/js-api-loader npm package.

npm i @googlemaps/js-api-loader

You will find the version of the following packages in React application.

react

^18.2.0

@googlemaps/js-api-loader

^1.15.1

Refer to the following article if you need help setting up Google Maps in your React project.
How to add Google Maps in React using the package

3. Implementation

Refer to the following files for implementation.

GMap.js

import React, { useEffect, useRef, useState } from 'react';

const GMap = () => {
  const googleMapRef = useRef(null);
  const [map, setMap] = useState(null);

  useEffect(() => {
    const googleMap = initGoogleMap();
    setMap(googleMap);
  }, []);

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

    const haight = new window.google.maps.LatLng(37.7699298, -122.4469157);
    const oceanBeach = new window.google.maps.LatLng(37.7683909618184, -122.51089453697205);

    // draw start marker
    new window.google.maps.Marker({
      position: haight,
      map
    });
    // draw end marker
    new window.google.maps.Marker({
      position: oceanBeach,
      map
    });

    // draw line between two points
    new window.google.maps.Polyline({
      path: [haight, oceanBeach],
      map
    });

    // draw marker to move from one point to another
    const marker = new window.google.maps.Marker({
      position: haight,
      map,
      icon: {
        url: '/marker-icon.png',
        scaledSize: new window.google.maps.Size(50, 50),
      }
    });

    // move marker from one point to another
    animatedMove(marker, haight, oceanBeach, 3);
  }, [map])

  const initGoogleMap = () => {
    return new window.google.maps.Map(googleMapRef.current, {
      center: new window.google.maps.LatLng(37.7699298, -122.4469157),
      zoom: 12
    });
  }

  const animatedMove = async (marker, moveFrom, moveTo, t, delta = 100) => {
    return new Promise(resolve => {
      const deltalat = (moveTo.lat() - moveFrom.lat()) / delta;
      const deltalng = (moveTo.lng() - moveFrom.lng()) / delta;
      let delay = 10 * t, count = 0;
      for (let i = 0; i < delta; i++) {
        (function (ind) {
          setTimeout(
            function () {
              let lat = marker.position.lat();
              let lng = marker.position.lng();
              lat += deltalat;
              lng += deltalng;
              marker.setPosition(new window.google.maps.LatLng(lat, lng));

              count++
              if (count === delta) {
                resolve(marker);
              }
            }, delay * ind
          );
        })(i)
      }
    })
  }

  return <div 300="" ref={googleMapRef} style={{ width: 600, height: }}>
}

export default GMap;</div>

App.js

import React, { useState, useEffect } from 'react';
import { Loader } from '@googlemaps/js-api-loader';
import GMap from './GMap';

// API key of the google map
const GOOGLE_MAP_API_KEY = '<your_google_map_api_key>';

const App = () => {
  const [loadMap, setLoadMap] = useState(false);

  useEffect(() => {
    const options = {
      apiKey: GOOGLE_MAP_API_KEY,
      version: "weekly",
      libraries: ['geometry']
    };

    new Loader(options).load().then(() => {
      setLoadMap(true);
    }).catch(e => {
      console.error('Sorry, something went wrong: Please try again later. Error:', e);
    });
  }, []);

  return (
    <div class="App">
      <h4>Move marker smoothly on Google Map in React - <a href="https://www.cluemediator.com">Clue Mediator</a></h4>
      {!loadMap ? <div>Loading...</div> : <gmap>}
      <br>
      <small><b>Note:</b> In order to make it work, you have to set the YOUR_GOOGLE_MAP_API_KEY in App.js file. </small>
    </gmap></div>
  );
}

export default App;
</your_google_map_api_key>

4. Output

Run your application and check the output in the browser.
Live Demo

That's it for today.
Thank you for reading. Happy Coding..!!

Demo & Source Code

GitHub Repository StackBlitz Project