react-native-web-community/react-native-web-maps

can't use custom marker on react native web maps

roozbeh95m opened this issue · 13 comments

hi I try to add custom marker to my map bu it aint working
what should I do?

Me too i'm trying to add the custom view but it's not working. Instead, it just shows the default map markers.

The problem is the Marker is not a named export in this repo, but it is in react-native-maps.

I used patch-package to solve this locally since I don't see movement here.

The solution would be to add this in src/index.js:

export {
  Marker,
  Polyline,
  Callout
}

To solve this in the meantime:

  1. Set up patch-package.

  2. Create a file patches/react-native-web-maps+0.3.0.patch

diff --git a/node_modules/react-native-web-maps/dist/index.js b/node_modules/react-native-web-maps/dist/index.js
index 47ed45f..1b90e84 100755
--- a/node_modules/react-native-web-maps/dist/index.js
+++ b/node_modules/react-native-web-maps/dist/index.js
@@ -1 +1,118 @@
-Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};var _jsxFileName='src/index.js';var _react=require('react');var _react2=_interopRequireDefault(_react);var _reactNative=require('react-native');var _reactGoogleMaps=require('react-google-maps');var _Marker=require('./Marker');var _Marker2=_interopRequireDefault(_Marker);var _Polyline=require('./Polyline');var _Polyline2=_interopRequireDefault(_Polyline);var _Callout=require('./Callout');var _Callout2=_interopRequireDefault(_Callout);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var GoogleMapContainer=(0,_reactGoogleMaps.withGoogleMap)(function(props){return _react2.default.createElement(_reactGoogleMaps.GoogleMap,_extends({},props,{ref:props.handleMapMounted,__source:{fileName:_jsxFileName,lineNumber:9}}));});var MapView=function(_Component){_inherits(MapView,_Component);function MapView(){var _ref;var _temp,_this,_ret;_classCallCheck(this,MapView);for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}return _ret=(_temp=(_this=_possibleConstructorReturn(this,(_ref=MapView.__proto__||Object.getPrototypeOf(MapView)).call.apply(_ref,[this].concat(args))),_this),_this.state={center:null},_this.handleMapMounted=function(map){_this.map=map;_this.props.onMapReady&&_this.props.onMapReady();},_this.getCamera=function(){return{zoom:_this.map.getZoom(),center:_this.map.getCenter(),heading:_this.map.getHeading()};},_this.onDragEnd=function(){var onRegionChangeComplete=_this.props.onRegionChangeComplete;if(_this.map&&onRegionChangeComplete){var center=_this.map.getCenter();onRegionChangeComplete({latitude:center.lat(),longitude:center.lng()});}},_temp),_possibleConstructorReturn(_this,_ret);}_createClass(MapView,[{key:'animateCamera',value:function animateCamera(camera){this.setState({zoom:camera.zoom});this.setState({center:camera.center});}},{key:'animateToRegion',value:function animateToRegion(coordinates){this.setState({center:{lat:coordinates.latitude,lng:coordinates.longitude}});}},{key:'render',value:function render(){var _this2=this;var _props=this.props,region=_props.region,initialRegion=_props.initialRegion,onRegionChange=_props.onRegionChange,onPress=_props.onPress,options=_props.options,defaultZoom=_props.defaultZoom;var center=this.state.center;var style=this.props.style||styles.container;var googleMapProps=center?{center:center}:region?{center:{lat:region.latitude,lng:region.longitude}}:{defaultCenter:{lat:initialRegion.latitude,lng:initialRegion.longitude}};var zoom=defaultZoom||(region&&region.latitudeDelta?Math.round(Math.log(360/region.latitudeDelta)/Math.LN2):initialRegion&&initialRegion.latitudeDelta?Math.round(Math.log(360/initialRegion.latitudeDelta)/Math.LN2):15);googleMapProps['zoom']=this.state.zoom?this.state.zoom:zoom;return _react2.default.createElement(_reactNative.View,{style:style,__source:{fileName:_jsxFileName,lineNumber:81}},_react2.default.createElement(GoogleMapContainer,_extends({handleMapMounted:this.handleMapMounted,containerElement:_react2.default.createElement('div',{style:{height:'100%'},__source:{fileName:_jsxFileName,lineNumber:84}}),mapElement:_react2.default.createElement('div',{style:{height:'100%'},__source:{fileName:_jsxFileName,lineNumber:85}}),onZoomChanged:function onZoomChanged(){_this2.setState({zoom:_this2.map.getZoom()});}},googleMapProps,{onDragStart:onRegionChange,onIdle:this.onDragEnd,defaultZoom:zoom,onClick:onPress,options:options,__source:{fileName:_jsxFileName,lineNumber:82}}),this.props.children));}}]);return MapView;}(_react.Component);MapView.Marker=_Marker2.default;MapView.Polyline=_Polyline2.default;MapView.Callout=_Callout2.default;var styles=_reactNative.StyleSheet.create({container:{height:'100%'}});exports.default=MapView;
\ No newline at end of file
+import React, { Component } from 'react';
+import { View, StyleSheet } from 'react-native';
+import { withGoogleMap, GoogleMap } from 'react-google-maps';
+import Marker from './Marker';
+import Polyline from './Polyline';
+import Callout from './Callout';
+
+const GoogleMapContainer = withGoogleMap(props => (
+  <GoogleMap {...props} ref={props.handleMapMounted} />
+));
+
+class MapView extends Component {
+  state = {
+    center: null,
+  };
+
+  handleMapMounted = map => {
+    this.map = map;
+    this.props.onMapReady && this.props.onMapReady();
+  };
+
+  getCamera = () => {
+    return {
+      zoom: this.map.getZoom(),
+      center: this.map.getCenter(),
+      heading: this.map.getHeading(),
+    };
+  };
+
+  animateCamera(camera) {
+    this.setState({ zoom: camera.zoom });
+    this.setState({ center: camera.center });
+  }
+
+  animateToRegion(coordinates) {
+    this.setState({
+      center: { lat: coordinates.latitude, lng: coordinates.longitude },
+    });
+  }
+
+  onDragEnd = () => {
+    const { onRegionChangeComplete } = this.props;
+    if (this.map && onRegionChangeComplete) {
+      const center = this.map.getCenter();
+      onRegionChangeComplete({
+        latitude: center.lat(),
+        longitude: center.lng(),
+      });
+    }
+  };
+
+  render() {
+    const { region, initialRegion, onRegionChange, onPress, options, defaultZoom } = this.props;
+    const { center } = this.state;
+    const style = this.props.style || styles.container;
+
+    const googleMapProps = center
+      ? { center }
+      : region
+      ? {
+          center: {
+            lat: region.latitude,
+            lng: region.longitude,
+          },
+        }
+      : {
+          defaultCenter: {
+            lat: initialRegion.latitude,
+            lng: initialRegion.longitude,
+          },
+        };
+    const zoom =
+      defaultZoom ||
+      (region && region.latitudeDelta
+        ? Math.round(Math.log(360 / region.latitudeDelta) / Math.LN2)
+        : initialRegion && initialRegion.latitudeDelta
+        ? Math.round(Math.log(360 / initialRegion.latitudeDelta) / Math.LN2)
+        : 15);
+    googleMapProps['zoom'] = this.state.zoom ? this.state.zoom : zoom;
+    return (
+      <View style={style}>
+        <GoogleMapContainer
+          handleMapMounted={this.handleMapMounted}
+          containerElement={<div style={{ height: '100%' }} />}
+          mapElement={<div style={{ height: '100%' }} />}
+          onZoomChanged={() => {
+            this.setState({ zoom: this.map.getZoom() });
+          }}
+          {...googleMapProps}
+          onDragStart={onRegionChange}
+          onIdle={this.onDragEnd}
+          defaultZoom={zoom}
+          onClick={onPress}
+          options={options}>
+          {this.props.children}
+        </GoogleMapContainer>
+      </View>
+    );
+  }
+}
+
+MapView.Marker = Marker;
+MapView.Polyline = Polyline;
+MapView.Callout = Callout;
+
+export { 
+  Marker,
+  Polyline,
+  Callout
+}
+
+const styles = StyleSheet.create({
+  container: {
+    height: '100%',
+  },
+});
+
+export default MapView;
diff --git a/node_modules/react-native-web-maps/src/index.js b/node_modules/react-native-web-maps/src/index.js
index dab5f22..1b90e84 100755
--- a/node_modules/react-native-web-maps/src/index.js
+++ b/node_modules/react-native-web-maps/src/index.js
@@ -103,6 +103,12 @@ MapView.Marker = Marker;
 MapView.Polyline = Polyline;
 MapView.Callout = Callout;
 
+export { 
+  Marker,
+  Polyline,
+  Callout
+}
+
 const styles = StyleSheet.create({
   container: {
     height: '100%',

I created a PR here: #37

@nandorojo

This change worked for me.

Thanks

This change worked for me, but it just made the app not crash. Custom Marker still does not work, custom pin and etc. Just stay with the standard view. Has anyone managed to get around this?

Edit: I was able to solve the problem of the custom pin by adding . The problem now is the custom Callout that is not displayed.

@Laferu I don't understand your solution. How did you get a custom marker?

I think using a custom marker would require upgrading to @react-google-maps/api.

@Laferu I don't understand your solution. How did you get a custom marker?

Instead of using a <MyCustomMarkerView {... marker} />, I used image={require ('../ assets / pin.png')} inside to get a custom pin. Unfortunately, using a custom component inside still doesn't work.

FWIW, I changed to mapbox while on web. So much better.

In playing around and looking at the source code

<MapView.Marker
 icon = {custom_icon}
>
</MapView.Marker>

will draw the custom_icon... I believe that custom_icon can be image in the asset folder, svg etc. NO code change is required. react-native-web-maps uses JustFly1984/react-google-maps-api
I'm still trying to figure out how to change the size of the icon, as width and height does not seem to be respected.

Hi @nandorojo, could give a bit more info on your mapbox configuration for web?
Im on an Expo managed workflow and I got to the point where I got the map running on web but cant even style it properly for web...
Are you running mapbox just for the web part? How did you configure mapbox? It doesnt seem to be available for expo..

on web i just straight up used the react library

Ahhh of course! Works like charm! 🫶