rnmapbox / maps

A Mapbox react native module for creating custom maps
MIT License
2.19k stars 834 forks source link

[Bug]: `LocationPuck` bearing not visible on Android #3391

Open philiplindberg opened 6 months ago

philiplindberg commented 6 months ago

Mapbox Implementation

Mapbox

Mapbox Version

default

React Native Version

0.73.4

Platform

Android

@rnmapbox/maps version

10.1.15

Standalone component to reproduce

import React from 'react'
import { Camera, LocationPuck, MapView } from '@rnmapbox/maps'

export default function App() {
  return (
    <MapView style={{ flex: 1 }}>
      <Camera
        zoomLevel={14}
        followUserLocation={true}
      />
      <LocationPuck
        puckBearingEnabled={true}
      />
    </MapView>
  )
}

Observed behavior and steps to reproduce

When rendering the LocationPuck with its bearing enabled on Android, the bearing does not appear. The bearing does appear on iOS.

Android iOS
unnamed (1) IMG_69F787A3B577-1

Expected behavior

The LocationPuck's bearing should be visible on both Android and iOS if enabled.

Notes / preliminary analysis

No response

Additional links and references

No response

smartmedev commented 6 months ago

You should use a custom image to show LocationPuck bearing on Android.

<MapboxGL.Images images={{ 
      "userLocationTopImage": markerUserIcon, 
      "headingArrow": headingIcon,
      "headingArrowXS": headingIconXS
      }} />

  <MapboxGL.LocationPuck
      topImage="userLocationTopImage"
      puckBearingEnabled={true} 
      puckBrearing="heading"
      bearingImage="headingArrow"
      visible={true}
      pulsing={{
          isEnabled: true,
          color: customColors.markerUserLocation,
          radius: 50.0,
      }} />
fahadShah23 commented 1 month ago

Hi there! for some reason this custom image is not working for my project in android. Is there any way i could add an SVG icon here instead of the PNG? I am trying to add the SVG Image but it is giving me some errors. Here are my project details:

React Native Version 0.70.15

Platform Android

@rnmapbox/maps version 10.1.15

Code:

import React from 'react'; import { View } from 'react-native'; import MapboxGL from '@rnmapbox/maps'; import markerUserIcon from './markerUserIcon.svg'; import headingIcon from './headingIcon.svg';

const ShowMap = () => { return ( <View style={{ flex: 1 }}> <MapboxGL.MapView style={{ flex: 1 }}> <MapboxGL.Images images={{ userLocationTopImage: markerUserIcon, headingArrow: headingIcon, }} /> {/ Other MapboxGL components and configurations /} </MapboxGL.MapView> ); }; export default ShowMap;

<MapboxGL.LocationPuck topImage="userLocationTopImage" puckBearingEnabled={true} puckBearing="heading" bearingImage="headingArrow" visible={true} pulsing={{ isEnabled: true, color: customColors.markerUserLocation, radius: 50.0, }} />

Error that i am encountering:

Error while updating property 'images' of a view managed by: RNMBXImages null next. value must not be null

mfazekas commented 1 month ago

@philiplindberg nope svg is not supported, sorry

fahadShah23 commented 1 month ago

Just a quick question @smartmedev or may be you can answer @mfazekas. How can i import the png images (markerUserIcon, headingIcon, headingIconXS) in my file? i am trying to import them like below in my working file but they does not seems to be working at my end.

import markerUserIcon from './markerUserIcon.png'; import headingIcon from './headingIcon.png'; import headingIconXS from './headingIconXS.png';

i have placed the icons at the same path as my project file on which i want to use the image. am i doing it correct or anything i need to change here?

smartmedev commented 1 month ago

Hi @fahadShah23 , in react native you cannot import images with "import". You need require. In my project I have an "icons.js" files where I require all required images then export them. (Note that all images are on /app/assets/images/ folder) On the other side, in components and screens I can import images from icons.js file.

Here's an example:

on my /app/utils/icons.js file:

const headingIcon = require('../assets/images/heading.png');
const markerUserIcon = require('../assets/images/marker-user.png');
const headingIconXS = require('../assets/images/heading-icon-xs.png');

export {
    headingIcon,
    markerUserIcon,
    headingIconXS
}

then on my /app/screens/HomeScreen.js import icons like this:

import { headingIcon, markerUserIcon, headingIconXS } from '../../utils/icons';

<MapboxGL.Images images={{ 
      "userLocationTopImage": markerUserIcon, 
      "headingArrow": headingIcon,
      "headingArrowXS": headingIconXS
      }} />

  <MapboxGL.LocationPuck
      topImage="userLocationTopImage"
      puckBearingEnabled={true} 
      puckBrearing="heading"
      bearingImage="headingArrow"
      visible={true}
      pulsing={{
          isEnabled: true,
          color: customColors.markerUserLocation,
          radius: 50.0,
      }} />
fahadShah23 commented 4 weeks ago

Hi @smartmedev thank you for your response. I have tried your solution but unfortunately image is still not appearing at my end. No sure what wrong i am doing here, can you please help identify. Here is my code, for instance i have placed my images on the same path/folder where my code file is. Below are the path to my implementation file ( where i need to get and show the image) and also the images path:

File Path: /home/{user}/{projectName}/libs/pattern/src/ui/features/Field/DrawField/DrawFieldFeature.native.tsx Images Path: /home/{user}/{projectName}/libs/pattern/src/ui/features/Field/heading.png /home/{user}/{projectName}/libs/pattern/src/ui/features/Field/DrawField/marker-user.png /home/{user}/{projectName}/libs/pattern/src/ui/features/Field/DrawField/heading-icon-xs.png

here is how i am getting them in my file i.e. 'DrawFieldFeature.native.tsx':

const headingIcon = require('./heading.png'); const markerUserIcon = require('./marker-user.png'); const headingIconXS = require('./heading-icon-xs.png');

Here is how i am using the above icons in Images & LocationPuck:

<Images
          images={{
            userLocationTopImage: markerUserIcon,
            headingArrow: headingIcon,
            headingArrowXS: headingIconXS,
          }}
        />
        <LocationPuck
          visible
          topImage="userLocationTopImage"
          bearingImage="headingArrow"
          puckBearingEnabled
          puckBearing="heading"
          pulsing={{ isEnabled: true, radius: 'accuracy', color: 'lightblue' }}
        />

Also just to check if the images are correctly imported in the file, i console the headingIcon, markerUserIcon and headingIconXS values and it gives my an numeric value i.e. 6. is it correct or it should give some kind or uri?

smartmedev commented 3 weeks ago

hi @fahadShah23 if images are in the same folder, have you tried to import like this ? Maybe absolute path could not work.

const headingIcon = require('heading.png');
const markerUserIcon = require('marker-user.png');
const headingIconXS = require('heading-icon-xs.png');

Also, use double quotes "" for the name of image in "images" attribute of element, you didn't put it in your example.

<MapboxGL.Images images={{ 
      "userLocationTopImage": markerUserIcon, 
      "headingArrow": headingIcon,
      "headingArrowXS": headingIconXS
      }} />

Let me know if it works, i think that require should give the path not numbers, but I'm not sure at all.

brien-crean commented 1 day ago

I have tried this but I can only get the bearingImage to show if I hide the topImage. They do not seem to play nice together.

import React from 'react';
import { Images, LocationPuck } from '@rnmapbox/maps';

export default function UserLocationMarker() {
  const headingIcon = require('./heading.png');
  const userIcon = require('./user-location.png');
  return (
    <>
      <Images
        images={{
          headingArrow: headingIcon,
          userLocation: userIcon,
        }}
      />
      <LocationPuck
        // bug? topImage and bearingImage do not work well together
        // topImage={'userLocation'}
        puckBearingEnabled={true}
        puckBearing={'heading'}
        bearingImage={'headingArrow'}
        visible={true}
        pulsing={{ isEnabled: true, radius: 50.0, color: 'lightblue' }}
      />
    </>
  );
}

I'm running Mapbox version 10.1.28 as I am on react native 0.73.8 currently.