Justin Priede
Justin Priede

Reputation: 119

react-native-maps custom map style

I created a json using google maps styling wizard. I then set that to a const under render and set that const to my MapView style but it renderers nothing when I do.

I am not sure the issue, Ideally I would like to have the style in a separate file but I was trying to start small.

How can I fix the current issue I am having as well as import and use the style from a separate file?

Here is a snack of my code that reproduces my exact error as well as the code below.

export default class Map extends React.Component {

 
  render() {
    const mapStyle = [
      {
        "featureType": "landscape.man_made",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.attraction",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "on"
          }
        ]
      },
      {
        "featureType": "poi.government",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      }
    ]

    return (
     <View style={{...StyleSheet.absoluteFillObject}}>
      <MapView
        style={mapStyle}
        provider={PROVIDER_GOOGLE}>
      </MapView>

      </View>
    );
  }
}

Upvotes: 2

Views: 3322

Answers (1)

David Scholz
David Scholz

Reputation: 9733

The custom google maps styling must be passed to the customMapStyle prop and you need to set a specific width and height in the normal style prop of the MapView. Setting absoluteFillObject does something different than you might have thought and according to the react-native documentation there is

Currently, there is no difference between using absoluteFill vs. absoluteFillObject.

Thus, absoluteFill is for the following use case.

A very common pattern is to create overlays with position absolute and zero positioning (position: 'absolute', left: 0, right: 0, top: 0, bottom: 0), so absoluteFill can be used for convenience and to reduce duplication of these repeated styles.

This will not set a height and a width! We need to do this manually which is documented here.

The following solves your problem.

const styles = ScaledSheet.create({
  map: {
width: Dimensions.get('window').width,
    height: Dimensions.get('window').height,
    
  },
...

The JSX component.

return (
     <View style={{...StyleSheet.absoluteFillObject}}>
      <MapView
        style={styles.map}
        customMapStyle={mapStyle}
        provider={PROVIDER_GOOGLE}>
      </MapView>

      </View>
    );

Here is the full solution.

export default class Map extends React.Component {

  render() {
    const mapStyle = [
      {
        "featureType": "landscape.man_made",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.attraction",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "on"
          }
        ]
      },
      {
        "featureType": "poi.government",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      }
    ]
    
    return (
     <View style={{...StyleSheet.absoluteFillObject}}>
      <MapView
        style={styles.map}
        customMapStyle={mapStyle}
        provider={PROVIDER_GOOGLE}>
      </MapView>

      </View>
    );
  }
}

const styles = ScaledSheet.create({
  map: {
width: Dimensions.get('window').width,
    height: Dimensions.get('window').height,
    
  },
  bubble: {
    justifyContent: 'center',
    alignItems: 'center',
    padding: 15,
  },
  carousel: {
    position: 'absolute',
    top: scale(625)
  },
  cardContainer: {
    backgroundColor: '#d1cfcf',
    height: scale(40),
    width: scale(300),
    borderRadius: 10,
    alignSelf: 'center',
    alignItems: 'center',
    justifyContent: 'center',
  },

  name: {
    color: 'black',
    fontSize: 22,

  }
});

Defining the customMapStyle in a separate file is plain JS and can be done as follows.

Define a new file, named CustomMapStyle.js and add the following content.

export const CustomMapStyle = [
      {
        "featureType": "landscape.man_made",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.attraction",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "on"
          }
        ]
      },
      {
        "featureType": "poi.government",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      }
    ]

Then use it as follows.

import {CustomMapStyle} from './CustomMapStyle'

...

render() {    
    return (
     <View style={{...StyleSheet.absoluteFillObject}}>
      <MapView
        style={styles.map}
        customMapStyle={CustomMapStyle}
        provider={PROVIDER_GOOGLE}>
      </MapView>

      </View>
    );
  }

I have updated your snack here.

The final result.

enter image description here

Upvotes: 3

Related Questions