16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React + Google Maps APIでモーダル上にマップを表示する

Posted at

Qiita初投稿です。最近ReactでGoogle Maps APIを扱うことが多いので自分用のTipsにする目的も兼ねて投稿してみました。

#最初の手順

  1. $ create-react-app 'プロジェクト名' で雛形を作成
  2. npm i --save react-modal コマンドでModalをコンポーネントとして扱えるようパッケージをinstall
  3. ここからMaps用APIキー取得
  4. public/index.html 内に<script>タグでAPIキーを埋め込み
    • 例: <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=取得したAPIキー"></script>

#コンポーネントの構造
以下の通り。

  • App (親コンポーネント)
    • Modal (子コンポーネント)
      • Map (孫コンポーネント) 

#ソースコード
###親コンポーネント(App) + 子コンポーネント(Modal)

App.js
import React, { Component } from 'react'
import './App.css'
import ReactDOM from 'react-dom'
import Modal from 'react-modal'

export default class App extends Component {
  constructor (props) {
    super(props)
    this.state = {
      showModal: false,
    }
    this.openModal = this.openModal.bind(this)
    this.closeModal = this.closeModal.bind(this)
  }

  openModal(){
    this.setState({showModal: true})
  }

  closeModal(){
    this.setState({showModal: false})
  }

  render(){
    const custom = {
      overlay : {
        background: 'rgba(0,0,0, .4)'
      },
      content : {
        top                   : '50%',
        left                  : '50%',
        right                 : 'auto',
        bottom                : 'auto',
        marginRight           : '-50%',
        transform             : 'translate(-50%, -50%)',
        width                 : '72%',
        height                : '80%'
      }
    }
    return (
      <div className="AppComponent">
        <input type="submit" className="button--submit" onClick={this.openModal} value="Open Map"/>
        <Modal isOpen={this.state.showModal} shouldCloseOnOverlayClick={true}
               onRequestClose={this.closeModal} style={custom} >
          <Map />
        </Modal>
      </div>
    )
  }
}

Modalコンポーネントはreact-modalからインポートしてそのまま使うので、スタイルなどもまとめて親コンポーネントのクラス内に記述。isOpenがTrueになった時にModalが表示されます。
今回は親コンポーネント上にボタンを置いて、それがクリックされることによってshowModalの状態をトグルして表示させています。
shouldCloseOnOverlayClickがTrueならオーバーレイ部分をクリックするとModalが閉じる。
styleでModalのスタイルを直接render()内に記述することで指定できるのですが、他に良い方法がありそう・・・
###孫コンポーネント(Map)

App.js
export class Map extends Component{
  constructor(props){
    super(props)

    this.state=({
      map: null,
    })
  }

  componentDidMount () {
    const map = new window.google.maps.Map(
      ReactDOM.findDOMNode(this.refs["map"]),
      // document.getElementById('modalMap'),
      {
        center: new window.google.maps.LatLng(35.466642, 139.622485), //横浜駅
        zoom: 17,
        mapTypeId: 'roadmap'
      }
    );
    this.setState({"map":map})
    console.log('map is open')
  }

  render(){
    return(
      <div className="modal--map">
        {/*<div ref="modalMap" className="modalMap"></div>*/} //document.getElementByIdを使う場合
        <div ref="map" id="modalMap"/>
      </div>
    )
  }

}

<div className="modal--map">がrenderされてDOMツリーに追加された後にMapオブジェクトをcomponentDidMount()で呼び出す仕組み。render内にmapのプロパティをベタ書きすると多分エラーになります、たしか。今回はReactDOM.findDOMNodeでref属性を持ったdivにMapを描画していますが、document.getElementByIdを使う書き方も可能です。

#まとめ
Mapをコンポーネントとして実装するならreact-google-mapsを素直に使うほうが間違いなく近道ではあるのですが、単にちょっと表示させたいなら上記の方法で済ますこともいいのではないでしょうか。
ここから、Map上のマーカーをさらに子コンポーネントとして追加したり、Modalの中にMapと並列となるコンポーネントを追加して何かウェブアプリを構築していくのもいいかなーと考えています。

#参考リンク
[Reactでcontextを利用してGoogleMapAPIを叩く(Map,Marker)]
(https://qiita.com/sh4869/items/fcbcc6dee76d42572566)

[Google Maps JavaScript API 概要]
(https://developers.google.com/maps/documentation/javascript/?hl=ja)

[react-modal]
(https://github.com/reactjs/react-modal)

16
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?