Raruto / leaflet-elevation

Leaflet plugin that allows to add elevation profiles using d3js
GNU General Public License v3.0
254 stars 82 forks source link

{{track_info}} not always correctly build #283

Open CoppensD opened 8 months ago

CoppensD commented 8 months ago

Checklist

Subject of the issue

Like described in #241 when using a custom summary the track_info is not always displayed.

The default summary is always correct and shown. But when you want to access the {{track_info}} object it's sometimes incomplete.

In console.log I get this for the track_info

{name: '2024-01-07 09:30'}

After a few refreshes I get

{name: '2024-01-07 09:30', distance: 12.251, time: 7788759, elevation_max: 75.57, elevation_min: 7.78, …}

and then I show the correct data for the track_info

My code is created as described in the demo for custom summary or #241

Steps to reproduce

https://raruto.github.io/leaflet-elevation/examples/leaflet-elevation_custom-summary.html did quite a few refreshes and suddenly I get no info 0 image

Environment

Windows 11 - Chrome version 120.0.6099.224

Link to your project

No response

Additional info

No response

Raruto commented 8 months ago

Hi @CoppensD,

If you some have time to investigate as explained in there #241 (and there #253)

otherwise just think differently, eg:

_waitFor(() => undefined !== controlElevation?.track_info?.distance).then(() => console.log(controlElevation.track_info));
/**
 * Function to wait for predicates.
 * 
 * @param { () => Boolean } predicate - A function that returns a bool
 * @param { number }        [timeout] - Optional maximum waiting time in ms after rejected
 * 
 * @see https://gist.github.com/chrisjhoughton/7890239?permalink_comment_id=4411125#gistcomment-4411125
 */
function _waitFor(predicate, timeout) {
  return new Promise((resolve, reject) => {
    const check = () => {
      if (!predicate()) return;
      clearInterval(interval);
      resolve();
    };
    const interval = setInterval(check, 100);
    check();
    if (timeout) {
      setTimeout(() => { clearInterval(interval); reject(); }, timeout);
    }
  });
}

👋 Raruto

CoppensD commented 8 months ago

I already worked with setInterval doesn't seem to solve anything.

I digged a bit further and noticed that eledata_added is sometimes loaded after eledata_loaded and is causing the issue. So it's not really an issue with the track_info.

I also noticed that my _start and _end are set to 0 for both lat and lng.

controlElevation.on("eledata_added", function(e){
  console.log(e);
  console.log("added");
})

controlElevation.on("eledata_loaded", ({ layer, name, track_info }) => {
  console.log(track_info); // only name visible
  console.log(track_info.distance); // undefined --> only when eledata_added is outputting after eledata_loaded
});

controlElevation.load(gpxFile);
CoppensD commented 8 months ago

For me this solved by adding my custom summary in the eledata_added and not the eledata_loaded event. For my _start and _end point I still need a solution.

Raruto commented 8 months ago

I also noticed that my _start and _end are set to 0 for both lat and lng.

As I have already pointed out in other issues, this is most likely a problem related to a misbehave of the internal "homemade" dependencies lazy loader:

https://github.com/Raruto/leaflet-elevation/blob/bd9316bd1b7e7784b3bf3d812960eaa808ad94d6/src/control.js#L809-L810

https://github.com/Raruto/leaflet-elevation/blob/bd9316bd1b7e7784b3bf3d812960eaa808ad94d6/src/control.js#L480-L481

When loading them statically, in the usual HTML way (eg. <script src="), I don't think there should be any problems.

Otherwise, please try to look at the code and propose your own solution.

👋 Raruto

CoppensD commented 8 months ago

Not sure if this is the best solution but I added the same lines from _initMapIntegrations(layer) into addData(d, layer)

https://github.com/Raruto/leaflet-elevation/blob/bd9316bd1b7e7784b3bf3d812960eaa808ad94d6/src/control.js#L32-L44

the lines I added between lines 38 and 39

if (this._data.length) {
  this._start.setLatLng(this._data[0].latlng);
  this._end.setLatLng(this._data[this._data.length - 1].latlng);
}