Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't add pulsingdot (custom animated) marker in real time data #11606

Closed
rajan-blackboxes opened this issue Mar 15, 2022 · 6 comments
Closed

Comments

@rajan-blackboxes
Copy link

Hello, I've got a problem of not showing a pulsing dot (marker) as expected, whenever somebody posts, It doesn't show, while data is received in real-time.

While with Axios, whenever I log in, I have a function to handle as

    getAPI
      .get("/post")
      .then((response) => {
         let userPostData = response.data;
        // make saperate geojson from api data for different problem condition
        userPostData["posts"].map(
          ({
            blood_group,
            condition,
            contact_number,
            coordinates,
            occur_date,
            problem_description,
            problem_name,
            problem_status,
          }) => {
	      putToGeojson(map.current, problem_status,condition, emergencyGj,blood_group,contact_number,coordinates,occur_date,problem_description,problem_name,urgentGj,anytimeGj,emergencyColor,urgentColor,anytimeColor)
          }
        );
      })

Where
emergencyGj, anytimeGj, urgentGj are geojson and emergencyColor, urgentColor, anytimeColor are color , these properties of geojson are put into putToGeojson . makeGeojson() creates geojson.

var emergencyGj = makeGeojson();
var urgentGj = makeGeojson();
var anytimeGj = makeGeojson();
const emergencyColor = {borderColor: "#FFFC00", innerColor: "#FF0000", pulseColor: "#FFC0CB",};
const urgentColor = {borderColor: "#FFFC00", innerColor: "violet", pulseColor: "#GGC0CB",};
const anytimeColor = {borderColor: "#FFFC00", innerColor: "green", pulseColor: "blue",};

I've already added a marker to for feature, ids in map using addToMap function before in useEffect hook.
addToMap(map.current, emergencyColor, urgentColor, anytimeColor, emergencyGj, anytimeGj, urgentGj)

blood_group, condition, contact_number, coordinates, occur_date,problem_description, problem_name,problem_status are properties for the marker.

using axios , after user is logged i can see as expected below
Alt Text

But problem starts when I use it for real-time, I've MongoDB watch function with socket.io, whenever there is a change or user posts some data through map.

   if(socket){
       socket.on("post.read", (data) => {
	   console.log(data.problem_status,data.condition, emergencyGj,data.blood_group,data.contact_number,data.coordinates,data.occur_date,data.problem_description,data.problem_name)
	   
	   putToGeojson(map.current,data.problem_status,data.condition, emergencyGj,data.blood_group,data.contact_number,data.coordinates,data.occur_date,data.problem_description,data.problem_name, urgentGj,anytimeGj,emergencyColor,urgentColor,anytimeColor)
		  // addToMap(map.current, emergencyColor, urgentColor, anytimeColor, emergencyGj, anytimeGj, urgentGj)
	})
   }

Here is my output of it , that doesn't shows blinking marker in real time ,
Alt Text

console logging I can see the data coming when posted, but pulsing dot doesn't show in the map, I've to refresh to show it.
But strangely when I put the default maker, it shows the marker coming in realtime throughout the users

if(socket){
       socket.on("post.read", (data) => {
	   const el = document.createElement('div');
	   el.className = 'marker';
	   new mapboxgl.Marker(el).setLngLat(data.coordinates).addTo(map.current);
	})
      }

output of above with default maker instead, which works

I want to have the same above result but with pulsing dot, which didn't work as I thought to be in real-time.

Is there something I've missed?
I appreciate your help.

Here are my helper functions that were used to create geojson, create layer, add properties and pulsing dot .
Helper functions map
I believe they are all correct as it worked as expected.I also tried to use scratch for socket.io only but it also doesn't works (from: https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/)

const putToGeojson = (map,problem_status,condition, emergencyGj,blood_group,contact_number,coordinates,occur_date,problem_description,problem_name,urgentGj,anytimeGj, emergencyColor,urgentColor,anytimeColor) => {
    // make a marker for each feature and add to the map
    if(problem_status === true) {
	switch (condition) {
                case "emergency":
                  emergencyGj.features.push({
                    type: "Feature",
                    geometry: { type: "Point", coordinates: coordinates},
                    properties: {
                      blood_group,
                      condition,
                      contact_number,
                      coordinates,
                      occur_date,
                      problem_description,
                      problem_name,
                    },
                  });
                  break;
                case "urgent":
                  urgentGj.features.push({
                    type: "Feature",
                    geometry: { type: "Point", coordinates: coordinates },
                    properties: {
                      blood_group,
                      condition,
                      contact_number,
                      coordinates,
                      occur_date,
                      problem_description,
                      problem_name,
                    },
                  });
                  break;
                case "anytime":
                  anytimeGj.features.push({
                    type: "Feature",
                    geometry: { type: "Point", coordinates: coordinates },
                    properties: {
                      blood_group,
                      condition,
                      contact_number,
                      coordinates,
                      occur_date,
                      problem_description,
                      problem_name,
                    },
                  });
                  break;
                default:
                  break;
        }
    }
}
const addToMap = (map, emergencyColor, urgentColor, anytimeColor, emergencyGj, anytimeGj, urgentGj) => {
    // make a marker for each feature and add to the map
    map.on("load",  async () => {
           map.addImage("emergency-pulsing-dot", createPulsingDot(100, map, emergencyColor), { pixelRation: 2 });
           map.addImage("urgent-pulsing-dot", createPulsingDot(100, map, urgentColor), { pixelRation: 2 });
        map.addImage("anytime-pulsing-dot", createPulsingDot(100, map, anytimeColor), { pixelRation: 2 });
          map.addSource("emergency-dot-point", {type: "geojson", data: emergencyGj,});
           map.addSource("urgent-dot-point", {type: "geojson", data: urgentGj,});
          map.addSource("anytime-dot-point", {type: "geojson", data: anytimeGj,});

          // add different layers based on condition
          addLayer(map, "emergency-layer-with-pulsating-dot", "emergency-dot-point", "emergency-pulsing-dot");
          addLayer(map, "urgent-layer-with-pulsating-dot", "urgent-dot-point", "urgent-pulsing-dot");
          addLayer(map, "anytime-layer-with-pulsating-dot", "anytime-dot-point", "anytime-pulsing-dot");
        });

        // mouse enter and leave for different conditions
        let postPopup = new mapboxgl.Popup({closeButton: false, closeOnClick: false,});
        mouseEnterAndLeave(map, "emergency-layer-with-pulsating-dot", postPopup);
        mouseEnterAndLeave(map, "urgent-layer-with-pulsating-dot", postPopup);
        mouseEnterAndLeave(map, "anytime-layer-with-pulsating-dot", postPopup);
}

Thank you.

@stepankuzmin
Copy link
Contributor

Thank you for your opening this ticket. To help the maintainers and community understand and address the problem accurately, please provide an isolated, minimal, complete, verifiable demonstration of the issue. We recommend using https://jsbin.com/. Please include information about the browser version and operating system used.

You might also consider posting your question to https://stackoverflow.com/questions/tagged/mapbox-gl-js to ask the community for help.

@rajan-blackboxes
Copy link
Author

rajan-blackboxes commented Apr 2, 2022

I'm able to add the default marker when like some data dynamically comes through socket.io event calls. But I'm unable to reproduce same instead of marker but with pulsing dot. While pulsing dot was working on axios calls.
Pulsing dot didn't shown up when i call same socket.io event replacing marker code .

@stepankuzmin
Copy link
Contributor

@rajan-blackboxes, could you please provide an isolated and reproducible example for this? This may be either a bug in GL JS, or there might be an issue with your implementation.

@rajan-blackboxes
Copy link
Author

Hello

I think i have solved the problem of not showing pulsing dot problem though problem still exists in another form. After month of trying to find solution of this i gave up and began moving to react-map-gl and used marker instead of pulsing dot idea.

But even I again tried to create a minimal with example given in https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/ . I didn't thought it was easy.

previously what i'v used is

if(socket){
socket.on("post.read", (data) => {
         map.current.on("load", () => {
                // add image , add source, add layer
              ......
          })
})
}

which was incorrect.


map.current.on("load", () => {
    if(socket){
       socket.on("post.read", (data) => {
                // add image , add source, add layer
                .....
        })
    }
})

Above code is correct.
By using this way i was able to add pulsing dot in real time in given coordinate.


I told problem exists in different form . Because As data is coming through the socket calls. I've to find a way to append every geojson features that come in real-time to different coordinates. So i found a way to append using dotGj.features.push to a geojson variable dotGj.

I created a geojson variable dotGj globally as

var dotGj = {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        geometry: {
          type: "Point",
          coordinates: [],
        },
        properties: {},
      },
    ],
  }

and on map load as below
I added image with pulsingDot , added source dot-point with data dotGj , added layer with source dot-point .

map.current.on("load", () => {
    if(socket){
       socket.on("post.read", (data) => {
                 // add image , add source, add layer

                map.current.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });
	        map.current.addSource("dot-point", {type: "geojson", data: dotGj}) // used data as dotGj
	        map.current.addLayer({'id': 'layer-with-pulsing-dot', 'type': 'symbol', 'source': 'dot-point', 'layout': {'icon-image': 'pulsing-dot'}});	


                // extract socket data    
                const {blood_group, condition, contact_number, coordinates, occur_date, problem_description, problem_name,} = data

                 // put socket data into `dotGj` features 
		  dotGj.features.push({
                    type: "Feature",
                    geometry: { type: "Point", coordinates: coordinates },
                    properties: {
                      blood_group,
                      condition,
                      contact_number,
                      coordinates,
                      occur_date,
                      problem_description,
                      problem_name,
                    },
                  })
                .....
        })
    }
})

After i used dotGj.features.push , pushed data into dotGj . Which doesn't shows in realtime.But i can see data is appended when i console.log dotGj . But somehow doesn't shows in map.

Thank you for your time looking into my issue.

@stepankuzmin
Copy link
Contributor

Hi @rajan-blackboxes,

You should add the image, source, and layer once, and then use setData to update the source.

const geoJson = {"type": "FeatureCollection", "features": []};

map.on("load", () => {
  map.addImage(...);
  map.addSource("sourceId", geoJson);
  map.addLayer(...);	


  socket.on("post.read", (data) => {
    geoJson.features.push({type: "Feature", geometry: {type: "Point", coordinates: data.coordinates }});
    map.getSource("sourceId").setData(geoJson);
  });
});

@rajan-blackboxes
Copy link
Author

Thank you . above solution solves the problem i have . setData is what i needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants