alexandra-c / leaflet-tracking-marker

✈ A React Leaflet library that allows developers to create custom markers that drifts to a certain point, computes their bearing angle using given coordinates and rotates accordingly.
MIT License
40 stars 13 forks source link

rotation marker is not working #2

Closed rautKunal closed 2 years ago

rautKunal commented 3 years ago

Thank you in advance everything is working fine but the marker is not rotating, please help on the issue

alexandra-c commented 3 years ago

Hello, can you send a sample of your code? Or if you can reproduce the issue in CodeSandbox it would be great.

rautKunal commented 3 years ago

Thank you for your response

// ---- file 1. start

import React, { useState, useEffect } from "react";
import L from "leaflet";

import { LeafletTrackingMarker } from "react-leaflet-tracking-marker";
import { Popup } from "react-leaflet";

import bwArrow from "../map/bwArrow.svg";

const icon = new L.icon({
  iconUrl: bwArrow,
  iconSize: [50, 50],
});

export default function AirplaneMarker({ data }) {
  const { latitude, longitude } = data;
  const [prevPos, setPrevPos] = useState([latitude, longitude]);

  useEffect(() => {
    if (prevPos[1] !== longitude && prevPos[0] !== latitude)
      setPrevPos([latitude, longitude]);
  }, [latitude, longitude, prevPos]);

  return (
    <LeafletTrackingMarker
      icon={icon}
      previousPosition={prevPos}
      position={[latitude, longitude]}
      duration={1000}
      keepAtCenter={false}
      rotationOrigin="center"
    />
  );
}

// ---- file 1. ends

// ---- file 2. Start

import React, { useState, useEffect, memo } from "react";
import axios from "axios";
import { MapContainer, TileLayer, useMap } from "react-leaflet";

import AirplaneMarker from "./AirplaneMarker";

const Map = ({ id }) => {
  const [data, setData] = useState({
    latitude: 21.26856666666667,
    longitude: 79.18924444444445,
  });
  const [plot, setPlot] = useState([21.26856666666667, 79.18924444444445]);
  // const [course, setCourse] = useState(0);

  const SetViewForMarker = () => {
    const mapHook = useMap();
    mapHook.setView(plot, mapHook.getZoom(), {
      animate: true,
      duration: 1,
    });
    // }
    return null;
  };
  const postRequest = async () => {
    const getMarker = {
      method: "get",
      url: `http://URL:port/path/${id}`,
      withCredentials: true,
      headers: { crossDomain: true, "Content-Type": "application/json" },
    };

    try {
      const resp = await axios(getMarker);
      console.log(resp.data.message);
      /**   sample object in message:
                 {Currenttime: "2021-09-24 09:36"
                  batterylevel: "0",
                  cellularsignal: "[{"cellId": 15913, "locationAreaCode": 60103, "mobileCountryCode": 404, "mobileNetworkCode": 22}]",
                  charge: null,
                  course: 14,
                  deviceid: 429,
                  fixtime: "2021-09-24 09:36",
                  ignition: "true",
                  latitude: 21.118664444444445,
                  longitude: 79.18347555555556,
                  motion: "true",
                  name: "MH 5783",
                  ntwrk: "0",
                  sat: "15",
                  speed: 42}
        */
      setData({
        latitude: resp.data.message.latitude,
        longitude: resp.data.message.longitude,
      });
      setPlot([resp.data.message.latitude, resp.data.message.longitude]);
      //    setCourse(resp.data.message.course);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    // first time load without delay:
    postRequest();

    // call in regular interval:
    const interval = setInterval(() => {
      postRequest();
    }, 8000);
    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div>
      {plot && (
        <MapContainer
          center={plot}
          zoom={16}
          scrollWheelZoom={true}
          style={{ width: "100%", height: "65vh" }}
        >
          <TileLayer
            attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          <SetViewForMarker />
          <AirplaneMarker data={data} />
        </MapContainer>
      )}
    </div>
  );
};
export default memo(Map);

// ---- file 2. ends

alexandra-c commented 3 years ago

Overall, looking at your code, it seems it should be working as intended. I do not know though what exactly your postRequest retrieves. First make sure that your AirplaneMarker retrieves different coordinates at every interval. If the marker get wrog coordinates it will set its rotation angle to 0° by default.

If you checked out the implementation of this marker, it just uses a simple mathematics formula to compute the bearing angle based on two different coordinates: https://github.com/alexandra-c/leaflet-tracking-marker/blob/0aef368e650c52d29f76fcee5dcbfa99938fa69c/src/LeafletTrackingMarker.js#L5-L11

Also, I think the interval of 8 seconds It's too long. This marker was intended to be used when you need to replicate a real time situation, like a moving Uber car, or the example from this library's Readme, the plane that is flowing on the map. For this last example I used a pooling time of 1s.

If you still cannot get to the bottom of this, try reproduce the issue in a CodeSandbox or a repository with mocked data so I can get a better look of it.

astritspancasd commented 2 years ago

I had the same issue but fixed it by changing the file LeafletTrackingMarger.js through commenting that line in the createMarker function.

var createMarker = function createMarker(_ref, ctx) {
  var position = _ref.position,
      previousPosition = _ref.previousPosition,
      options = _objectWithoutProperties(_ref, _excluded);

  var bearingAngle = computeBearing(previousPosition, position);
`  // this line here  if (bearingAngle !== previousBearingAngle) previousBearingAngle = bearingAngle; `
  var instance = new _BaseMarker.BaseMarker(position, _objectSpread(_objectSpread({}, options), {}, {
    bearingAngle: bearingAngle
  }));
  return {
    instance: instance,
    context: _objectSpread(_objectSpread({}, ctx), {}, {
      overlayContainer: instance
    })
  };
};
alexandra-c commented 2 years ago

I had the same issue but fixed it by changing the file LeafletTrackingMarger.js by commenting that line in the createMarker function.

var createMarker = function createMarker(_ref, ctx) {
  var position = _ref.position,
      previousPosition = _ref.previousPosition,
      options = _objectWithoutProperties(_ref, _excluded);

  var bearingAngle = computeBearing(previousPosition, position);
  // this line here  if (bearingAngle !== previousBearingAngle) previousBearingAngle = bearingAngle; 
  var instance = new _BaseMarker.BaseMarker(position, _objectSpread(_objectSpread({}, options), {}, {
    bearingAngle: bearingAngle
  }));
  return {
    instance: instance,
    context: _objectSpread(_objectSpread({}, ctx), {}, {
      overlayContainer: instance
    })
  };
};

You are right, it seems like the previousBearingAngle was set twice, once before the rotation actually happens and once after, causing a reset of the angle ( the default values being 0 degrees ).