https://github.com/tomchentw/react-google-maps を使用した非常に単純なreactアプリケーションがありますが、現在のマップへの参照を取得する方法やアクセスする方法を理解するのに苦労していますカスタムコンポーネントの_google.maps.Map
_オブジェクト。
リポジトリで this を見つけましたが、投稿を読んだ後、まだ少し混乱しています。
DirectionsRenderer の例からアプリケーションの構築を開始しています。
次に実行したいのは、開始点を選択してGoogleMapsオートコンプリートAPIを使用するための独自のカスタムコンポーネントを追加することです。
はい、パッケージにそのためのコンポーネントがすでに含まれていることは知っていますが、地図上で場所を検索するだけでなく、もう少し行う必要があります。
私のニーズを達成するために、私は次のようなことをします
_const autocomplete = new google.maps.places.Autocomplete(node);
autocomplete.bindTo('bounds', map);
_
ここで、node
はオートコンプリート機能をバインドしている要素であり、map
は_google.maps.Map
_オブジェクトのインスタンスです。
これまでの私のアプリケーション:
App.jsx
_const App = ({ store }) => (
<Provider store={store}>
<div>
<Sidebar>
<StartingPoint defaultText="Choose starting point…" />
</Sidebar>
<GoogleApiWrapper />
</div>
</Provider>
);
_
GoogleApiWrapper
_const GoogleMapHOC = compose(
withProps({
googleMapURL: 'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=__GAPI_KEY',
loadingElement: <div style={{ height: '100vw' }} />,
containerElement: <div style={{ height: '100vh' }} />,
mapElement: <div style={{ height: '100%' }} />,
}),
withScriptjs,
withGoogleMap,
lifecycle({
componentDidMount() {
const DirectionsService = new google.maps.DirectionsService();
// make google object available to other components
this.props.onLoad(google);
DirectionsService.route({
Origin: new google.maps.LatLng(41.8507300, -87.6512600),
destination: new google.maps.LatLng(41.8525800, -87.6514100),
travelMode: google.maps.TravelMode.DRIVING,
}, (result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result,
});
} else {
console.error(`error fetching directions ${result}`);
}
});
},
}),
)(props => (
<GoogleMap
ref={props.onMapMounted}
defaultZoom={13}
defaultCenter={new google.maps.LatLng(37.771336, -122.446615)}
>
{props.directions && <DirectionsRenderer directions={props.directions} />}
</GoogleMap>
));
_
ラッパーの外部で_google.maps.Map
_オブジェクトにアクセスできない場合は、代わりに、マップを含む要素への参照にアクセスして、new google.maps.Map(ref_to_elem, options);
をインスタンス化できるようにします。
どんな助けでも大歓迎です!
React-google-mapsのドキュメント、例、および問題を完全に読んだ後、私はそれを知るようになりました パッケージはサポートしていません アプリケーションのために行う必要がある多くのこと。
そうは言っても、 Fullstack React によって行われた作業に基づいて、独自のGoogle MapsAPIラッパーを書き始めました。 ここ または ここ であるため、以下で使用するユーティリティの多くを省略しました。
そうは言っても、私の解決策は、Googleマップコンテナを高次のコンポーネントでラップし、Map
オブジェクトを介してwindow
オブジェクトを公開することです。
アプリ
const App = ({ store }) => (
<Provider store={store}>
<div>
<Sidebar>
<StartingPoint />
{/* TODO */}
</Sidebar>
<GoogleMap />
</div>
</Provider>
);
containers/GoogleMap /wrapper.jsxGoogleMapの高次コンポーネントがGoogleMapコンテナをラップします
const defaultCreateCache = (options) => {
const opts = options || {};
const apiKey = opts.apiKey;
const libraries = opts.libraries || ['places'];
const version = opts.version || '3.24';
const language = opts.language || 'en';
return ScriptCache({
google: GoogleApi({
apiKey,
language,
libraries,
version,
}),
});
};
const wrapper = options => (WrappedComponent) => {
const createCache = options.createCache || defaultCreateCache;
class Wrapper extends Component {
constructor(props, context) {
super(props, context);
this.scriptCache = createCache(options);
this.scriptCache.google.onLoad(this.onLoad.bind(this));
this.state = {
loaded: false,
google: null,
};
}
onLoad() {
this.GAPI = window.google;
this.setState({ loaded: true, google: this.GAPI });
}
render() {
const props = Object.assign({}, this.props, {
loaded: this.state.loaded,
google: window.google,
});
const mapRef = (el) => { this.map = el; };
return (
<div>
<WrappedComponent {...props} />
<div ref={mapRef} />
</div>
);
}
}
Wrapper.propTypes = {
dispatchGoogleAPI: PropTypes.func,
};
Wrapper.defaultProps = {
dispatchGoogleAPI: null,
};
return Wrapper;
};
export default wrapper;
containers/GoogleMap/index.jsxGoogleマップコンテナ
class Container extends Component {
constructor(props) {
super(props);
this.loadMap = this.loadMap.bind(this);
this.calcRoute = this.calcRoute.bind(this);
}
componentDidUpdate() {
const { Origin, destination, route } = this.props;
this.calcRoute(Origin, destination);
}
loadMap(node) {
if (this.props && this.props.google) {
const { google } = this.props;
// instantiate Direction Service
this.directionsService = new google.maps.DirectionsService();
this.directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true,
});
const zoom = 13;
const mapTypeId = google.maps.MapTypeId.ROADMAP;
const lat = 37.776443;
const lng = -122.451978;
const center = new google.maps.LatLng(lat, lng);
const mapConfig = Object.assign({}, {
center,
zoom,
mapTypeId,
});
this.map = new google.maps.Map(node, mapConfig);
this.directionsDisplay.setMap(this.map);
// make the map instance available to other components
window.map = this.map
}
}
calcRoute(Origin, destination) {
const { google, route } = this.props;
if (!Origin && !destination && !route) return;
const waypts = [];
waypts.Push({
location: new google.maps.LatLng(37.415284, -122.076899),
stopover: true,
});
const start = new google.maps.LatLng(Origin.lat, Origin.lng);
const end = new google.maps.LatLng(destination.lat, destination.lng);
this.createMarker(end);
const request = {
Origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
};
this.directionsService.route(request, (response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.directionsDisplay.setDirections(response);
const route = response.routes[0];
console.log(route);
}
});
this.props.calculateRoute(false);
}
createMarker(latlng) {
const { google } = this.props;
const marker = new google.maps.Marker({
position: latlng,
map: this.map,
});
}
render() {
return (
<div>
<GoogleMapView loaded={this.props.loaded} loadMap={this.loadMap} />
</div>
);
}
}
const GoogleMapContainer = wrapper({
apiKey: ('YOUR_API_KEY'),
version: '3', // 3.*
libraries: ['places'],
})(Container);
const mapStateToProps = state => ({
Origin: state.Trip.Origin,
destination: state.Trip.destination,
route: state.Trip.route,
});
const mapDispatchToProps = dispatch => ({
dispatchGoogleMap: (map) => {
dispatch(googleMap(map));
},
calculateRoute: (route) => {
dispatch(tripCalculation(route));
},
});
const GoogleMap = connect(mapStateToProps, mapDispatchToProps)(GoogleMapContainer);
export default GoogleMap;
あなたはReact refs:
<GoogleMap ref={(map) => this._map = map} />
function someFunc () {
//using, for example as:
this._map.getCenter()
this._map.setZoom(your desired zoom);
}
私がreact-reduxアプリケーションで今行ったことは、reactコンポーネントのGoogleMapの外部にグローバル変数マップを割り当てることです。
/*global google*/
// your imports //
var map;
class GoogleMap extends Component {
constructor(props) {
super(props);
this.state = {
// your states
};
}
// your functions
componentWillReceiveProps(nextProps) {
}
componentDidMount() {
// code
// render googlemap
map = new google.maps.Map(this.refs.map, yourMapProps);
// add click event listener to the map
map.addListener('click', function(e) {
//code
});
//viewport listener
map.addListener('idle', function(){
// code
});
}
render() {
return (
<div id="map" ref="map">
{places.map((place) => {
return(<Marker place={place} key={place.key} map={map} />);
})}
</div>
}
}
function mapDispatchToProps(dispatch) {
//code
}
export default connect(mapDispatchToProps)(GoogleMap);
マップを小道具として子コンポーネントに渡します。
/*global google*/
import React, { Component } from 'react';
class Marker extends Component {
componentDidMount() {
this.renderMarker();
}
renderMarker() {
var { place, map } = this.props;
place.setMap(map);
}
render() {
return null;
}
}
export default Marker;
それが良い習慣かどうかはわかりません。 Buそれは動作します。私は、マップオブジェクトをグローバルwindows.mapとして設定しないようにする方法を見つけようとしました。これは、シングルトンなどに関するすべてのものを読み取ります。そして、これが私の頭に浮かびました。ブラウザのconcoleにwindow.mapと入力すると、div id = "map"が表示されます。
import {GoogleMap, withGoogleMap} from 'react-google-maps';
import {MAP} from 'react-google-maps/lib/constants';
const MapComponent = withGoogleMap(() => (
{/*Here you have access to google.maps.Map object*/}
<GoogleMap ref={(map) => map.context[MAP]}/>
));
const Map = ({locations}) => (
<MapComponentClass
containerElement={MapComponent}
mapElement={MapComponent}
locations={locations}/>
);
export default Map;