react-native-mapbox-gl icon indicating copy to clipboard operation
react-native-mapbox-gl copied to clipboard

User location rendering behind line drawn from user's previous locations

Open cesar3030 opened this issue 5 years ago • 3 comments

Hello there!



I’m tracking a user position and want to draw a line to see the path he walked.


How would you do that with this library?



I tried to implement it that way:

  • When onUserLocationUpdate from the MapboxGL.MapView component invokes the callback, it updates my container current position state (an array of coordinates [lng, lat]) which will cause the container to be re-rendered.
  • The render function of my container draws the map and a MapboxGL.Animated.LineLayer within a MapboxGL.Animated.ShapeSource that contains the line of the user's previous coordinates. The method that renders the line adds the currentPosition stored in the state to an array of “previous current positions” called recordedPath also stored in the state. After adding the current position to the recorderPath, a line is created from the coordinates of the recordedPath (array of coordinates) and a MapboxGL.Animated.ShapeSource component is returned.



I’m facing 3 issues with this implementation:

  • The CPU goes crazy since the component keeps rendering every time onUserLocationUpdate fires is callback
  • Sometimes, the userTrackingMode={MapboxGL.UserTrackingModes.Follow} of MapboxGL.MapView is not working (user's location does not stay on the center of the screen)
  • The line is drawn ahead of the user’s location. Like if user’s location was delayed by a couple of coordinates points.

mapbox-issue

Here is the element that renders the map and the line:

import React, { Component } from 'react';
import { View } from 'react-native';
import MapboxGL from '@mapbox/react-native-mapbox-gl';
import {lineString as makeLineString} from '@turf/helpers';

const layerStyles = MapboxGL.StyleSheet.create({
  progress: {
    lineColor: '#314ccd',
    lineWidth: 3,
  },
});

export default class RecordingScreen extends Component {
  constructor(props) {
    super(props);
    this.state = {
      recordedPath: [],
      currentPoint: null,
    };
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <MapboxGL.MapView
          showUserLocation={true}
          userTrackingMode={MapboxGL.UserTrackingModes.Follow}
          onUserLocationUpdate={this.onUserLocationUpdate}
          styleURL={MapboxGL.StyleURL.Street}
          zoomLevel={15}
          style={{ flex: 1}}
        >
          {this.renderProgressLine()}
        </MapboxGL.MapView>
      </View>
    );
  }

  onUserLocationUpdate = (e) => {
    const { longitude, latitude } = e.coords;
    this.setState({
      currentPoint: [longitude, latitude],
    })
    console.log(JSON.stringify(e))
  }

  renderProgressLine = () => {
    if (!this.state.currentPoint) {
      return null;
    }

    const coords = this.state.recordedPath;
    coords.push(this.state.currentPoint)

    if (coords.length < 2) {
      return null;
    }

    const lineString = makeLineString(coords);

    return (
      <MapboxGL.Animated.ShapeSource id="progressSource" shape={lineString}>
        <MapboxGL.Animated.LineLayer
          id="progressFill"
          style={layerStyles.progress}
        />
      </MapboxGL.Animated.ShapeSource>
    );
  }
}

To test this component, I use the iOS Emulator with Debug > Location > City Run, enabled.

Thanks for your help!

cesar3030 avatar May 27 '19 15:05 cesar3030

The line drawn ahead is because the userlocation gets updated in steps, but the UI is animated smoothly. So basicly you push the userlocation to the line array and the line gets rendered. But the currentposition of the user is animated slowly betweetn both the last and current user location. I'm facing the same issue, but when testing it on a real device its looking better than in the simulator.

Blackfaded avatar Mar 30 '20 06:03 Blackfaded

Thanks for the info! I will soon be working on this again If I find a better way to do it, I'll ping you :)

cesar3030 avatar Mar 30 '20 20:03 cesar3030

Any updates on it? Not tried on a real device yet, but have the same visual effect while simulating location.

robomanus avatar Dec 28 '20 19:12 robomanus