skip to Main Content

I’m building a gig guide app using react native/react native maps.

I have location markers within my MapView, and each marker has text associated with it that displays the gig venue, as follows:

enter image description here

The problem however is that since I’ve added the text to the marker, the marker doesn’t remain fixed on it’s coordinates – and as the user zooms out, the location of the marker becomes more displaced.

Any ideas on how to add text information to each marker without causing this displacement? I’m not using callouts, because that has presented other issues. Code for the MapView as follows:

      <MapView
        initialRegion={{
          latitude: -41.29416,
          longitude: 174.77782,
          latitudeDelta: 0.03,
          longitudeDelta: 0.03,
        }}
        style={styles.map}
        customMapStyle={mapStyle}
      >

        {gigsToday.map((gig, i) => {
          let venueName
          if(gig.venue.length > 12){
            venueName = `${gig.venue.substring(0,5)}...`
          } else {
            venueName = gig.venue
          }
          return (
            <Marker
            style = {{flexDirection:'column'}}
            key={i}
            coordinate={{
              latitude: gig.location.latitude,
              longitude: gig.location.longitude,
            }}
            image={require("../assets/Icon_Gold_48x48.png")}
            description = 'test'
            onPress = {() => {
              navigation.navigate("GigDetails", {
                venue: gig.venue,
                date: selectedDateString,
                gigName: gig.gigName,
                image: gig.image,
                blurb: gig.blurb,
                isFree: gig.isFree,
                genre:gig.genre,
                dateAndTime: gig.dateAndTime.seconds,
                tickets:gig.tickets
              })
            }}
          >
              <Text style = {styles.gigInfo_text}>{venueName}</Text> 
          </Marker>
          )
          })}
      </MapView>

The entire component:

MapView.js

import { useState, useMemo } from "react";
import {
  StyleSheet,
  Text,
  View,
  Pressable,
  Image,
  TouchableOpacity,
} from "react-native";
import MapView from "react-native-maps";
import { Marker, Callout } from "react-native-maps";
import CalloutView from "./CalloutView";
import { mapStyle } from "../util/mapStyle";
import { useGigs } from "../hooks/useGigs";
import { AntDesign } from "@expo/vector-icons";


const GigMap = ({ navigation }) => {
  const [selectedDateMs, setSelectedDateMs] = useState(Date.now());
  const gigs = useGigs();


  //generates current date in format DD/MM/YYYY
  const selectedDateString = useMemo(() => {
    const date = new Date(selectedDateMs);
    const dateToString = date.toString().slice(0,15)
    return dateToString // returns in form 'Tue Dec 20 2022'
  }, [selectedDateMs]);


  //Filtering through gigs to return only current day's gigs
  const gigsToday = gigs.filter((gig) => {
    const gigDate1 = new Date(gig.dateAndTime.seconds*1000)   
    const gigDate2 = gigDate1.toString().slice(0,15) //return form 'Tue Dec 20 2022'
    return gigDate2 === selectedDateString
  })


  //increments date by amount
  const addDays = (amount) => {
    setSelectedDateMs((curr) => curr + 1000 * 60 * 60 * 24 * amount);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.headerText}>{`Gigs on ${selectedDateString}`}</Text>

      <View style={styles.imageText}>
        <Text style = {styles.subHeader}>Tap on</Text>
        <Image
          style={styles.image}
          source={require("../assets/Icon_Gold_48x48.png")}
        />
        <Text style = {styles.subHeader}> to see gig info</Text>
      </View>

      <MapView
        initialRegion={{
          latitude: -41.29416,
          longitude: 174.77782,
          latitudeDelta: 0.03,
          longitudeDelta: 0.03,
        }}
        style={styles.map}
        customMapStyle={mapStyle}
      >

        {gigsToday.map((gig, i) => {
          let venueName
          if(gig.venue.length > 12){
            venueName = `${gig.venue.substring(0,5)}...`
          } else {
            venueName = gig.venue
          }
          return (
            <Marker
            style = {{flexDirection:'column'}}
            key={i}
            coordinate={{
              latitude: gig.location.latitude,
              longitude: gig.location.longitude,
            }}
            image={require("../assets/Icon_Gold_48x48.png")}
            description = 'test'
            onPress = {() => {
              navigation.navigate("GigDetails", {
                venue: gig.venue,
                date: selectedDateString,
                gigName: gig.gigName,
                image: gig.image,
                blurb: gig.blurb,
                isFree: gig.isFree,
                genre:gig.genre,
                dateAndTime: gig.dateAndTime.seconds,
                tickets:gig.tickets
              })
            }}
          >
              <Text style = {styles.gigInfo_text}>{venueName}</Text> 
          </Marker>
          )
          })}
      </MapView>

      <View style={styles.buttonOptions}>
        <TouchableOpacity onPress={() => addDays(-1)} style = {styles.touchable}>
          <AntDesign name="caretleft" size={36} color="#778899" />
          <Text style = {{fontFamily:'Helvetica-Neue', color:'#778899'}}>Previous day</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => addDays(1)} style = {styles.touchable}>
          <AntDesign name="caretright" size={36} color="#778899" />
          <Text style = {{fontFamily:'Helvetica-Neue',color:'#778899'}}>Next day</Text>
        </TouchableOpacity>
      </View>
    </View>

  );
};

const styles = StyleSheet.create({
  container: {
    flexDirection: "column",
    alignItems: "center",
  },
  map: {
    height: 450,
    width: '100%',
    margin: 10,
  },
  gigInfo: {
    // backgroundColor: '#68912b',
    // marginTop:20
  },
  gigInfo_text: {
    color:'white',
    fontFamily: 'Helvetica-Neue',
    fontSize:12,
    paddingTop:22
  },
  gigInfo_text_genre: {
    color:'white',
    fontFamily: 'Helvetica-Neue',
    transform: [
      {translateY: -5}
    ]
  },
  headerText: {
    color: "black",
    fontSize: 25,
    marginTop: 5,
    fontFamily:'Sofia-Pro',
    fontStyle:'bold',
    marginBottom:10,
    marginTop: 15
  },
  callout: {
    width: 'auto',
    height: 'auto',
    backgroundColor:'azure'
  },
  buttonOptions: {
    flexDirection: "row",
    justifyContent: "space-around",
    width: "92%",
  },
  buttonOptionsText: {
    margin: 5,
  },
  image: {
    height: 20,
    width: 20,
    paddingBottom: 10,
    margin: 0,
  },
  imageText: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
  },
  touchable: {
    flexDirection:'column',
    alignItems:'center'
  },
  subHeader: {
    fontStyle: 'italic',
    fontFamily:'Helvetica-Neue',
    color:'#778899'
  }
});

export default GigMap;

2

Answers


  1. You can put the Text into a View with an absolute position. You’ll have to tweak the text position to get it where you like it, but it won’t be included in the calculation of where the marker goes.

    Login or Signup to reply.
  2. Here you can do this like this.it has custom marker + image and text at the exact coordinate.

    <Marker
            coordinate={{
              latitude: pickup.location.coordinates[1],
              longitude: pickup.location.coordinates[0],
            }}>
            <Image
              style={styles.customerImgMap}
              source={{uri: this.customerAvatar}}
            />
            <View style={styles.customerView}>
              <Text
                style={{
                  fontFamily: fonts.semibold,
                  fontSize: RFValue(12),
                  color: AppColor.defaultBackground,
                }}>
                Pick-up address:
              </Text>
              <Text
                numberOfLines={2}
                style={{
                  fontFamily: fonts.semibold,
                  fontSize: RFValue(12),
                  width: widthPercentageToDP(50),
                }}>
                {pickup?.address}
              </Text>
            </View>
          </Marker>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search