birkir / react-native-carplay

CarPlay with React Native
https://birkir.dev/react-native-carplay/
MIT License
642 stars 107 forks source link

Map panning buttons not working #69

Closed jqn closed 2 years ago

jqn commented 2 years ago

Hi! first of all thanks for this library. I'm trying to implement a map and would like to have the user pan or zoom in/out. I'm able to render the map and everything seems to work, except for the buttons. Here is a screenshot of the apple example app that has the same feature, unfortunately, there is no objective c example. Any advice on this, should the buttons work and I'm doing something wrong or they are not finished and need to be finished. Is there somewhere to find an example of how to fix them, etc, thanks in advance.

Screen Shot 2021-10-26 at 6 30 27 PM
tomdye commented 2 years ago

You need to use the onPanWithDirection event from the MapTemplate in your JS code to pan the underlying map when those buttons are pressed. Something like:

function onMapPanWithDirection({ direction }) {
    switch (direction) {
        case 'up':
            // go up    
            break;
        case 'down':
            // go down
            break;
        case 'left':
            // go left
            break;
        case 'right':
            // go right
            break;
    }
}
jqn commented 2 years ago

Ok, I get it so it would look something like this if I was to add to the example app in this repo:

useEffect(()=> {
    const mapConfig: MapTemplateConfig = {
      component: MapView,
      onAlertActionPressed(e) {
        console.log(e);
      },
      onStartedTrip() {
        onStartNavigation();
      },
      onPanWithDirection(e) {
        onMapPanWithDirection(e);
      },
    };
...

}, []);

...

const onMapPanWithDirection = ({direction}) => {
    switch (direction) {
        case 'up':
            // go up    
            break;
        case 'down':
            // go down
            break;
        case 'left':
            // go left
            break;
        case 'right':
            // go right
            break;
    }
};

...

So in other words these methods in MapTemplate.ts are available:

  get eventMap() {
    return {
      alertActionPressed: 'onAlertActionPressed',
      mapButtonPressed: 'onMapButtonPressed',
      panWithDirection: 'onPanWithDirection',
      panBeganWithDirection: 'onPanBeganWithDirection',
      panEndedWithDirection: 'onPanEndedWithDirection',
      selectedPreviewForTrip: 'onSelectedPreviewForTrip',
      didCancelNavigation: 'onDidCancelNavigation',
      startedTrip: 'onStartedTrip',
    };
  }

Thanks a lot @tomdye for your help and for clarifying this, I'll work on some kind of pull request to get this added to the example app.

tomdye commented 2 years ago

Yup, that looks about right to me. Are they not in the typings for the map template? ie. do they not autocomplete?

jqn commented 2 years ago

They do not seem to autocomplete for me but it might have to do with my local environment.

jqn commented 2 years ago

@tomdye this is what I came up with so far. I also found a way to add extra buttons to the map template.

const mapTemplate = useRef(
  new MapTemplate({
    component: MapView,
    onAlertActionPressed(e) {
      console.log(e)
    },
    onMapButtonPressed: ({ id }) => {
      console.log('id', id)
    },
    mapButtons: [
      // { id: 'markerImage', image: zoomOutIcon, titleVariants: ['marker'] },
      { id: 'zoomIn', image: zoomInIcon, titleVariants: ['+'] },
      { id: 'zoomOut', image: zoomOutIcon, titleVariants: ['-'] },
    ],
  }),
)
Screen Shot 2021-11-06 at 9 31 37 AM
tomdye commented 2 years ago

yup, that looks correct to me. Which map view are you using? Feel free to raise a more complete example as a PR to the repo to help others. Thanks

jqn commented 2 years ago

@tomdye I'm using react-native-mapbox-gl, thanks for all your help. I was wondering how would I interact with the map template component, in my case the MapView. I would like to set the zoom on the map when the zoom buttons are pressed. I was thinking one way would be to use the Context API but is there a different way that I should know.

tomdye commented 2 years ago

you do that within the JS code, when the template triggers the onMapButton (i forget the name) event, either set some state which the map can react to or use a ref to call a function on the map.

jqn commented 2 years ago

@tomdye I have been trying to create a ref to the map template component but it doesn't seem to be working. I'm following the example code. Would you kindly give me a hint on how to do this? I'll sincerely appreciate it.

const mapViewRef = useRef(null)

useEffect(()=> {
    const mapConfig: MapTemplateConfig = {
      component: () => <MapView ref={mapViewRef}/>,
      onAlertActionPressed(e) {
        console.log(e);
      },
      onStartedTrip() {
        onStartNavigation();
      },
      onPanWithDirection(e) {
        onMapPanWithDirection(e);
      },
    };