React で Google Map API を使う

Posted: , Modified:   GoogleMapAPI React CoffeeScript Qiita

本稿は Qiita 投稿記事 のバックアップです.

はじめに

React が面白いので,Google Map を使っているアプリも React ベースに移行しようと思った.予想通り,既にライブラリ react-google-maps があって,これを使えば良いのだけれど,どうもオーバースペックな感じがする.そこで簡易コンポーネントを作った.

ソースコード

Map コンポーネントのソースコードです.よりによって Coffee-React です.

Map = React.createClass

  propTypes:
    height: React.PropTypes.number.isRequired
    lat: React.PropTypes.number.isRequired
    lng: React.PropTypes.number.isRequired

  getInitialState: ->
    map: null
    mousemove_listener: null
    touchmove_listener: null

  componentDidMount: ->
    map = new google.maps.Map React.findDOMNode(@),
      center: new google.maps.LatLng(@props.lat, @props.lng)
      zoom: 15
      mapTypeId: google.maps.MapTypeId.ROADMAP

    if "onmousedown" of window
      # Use mouse events
      @setState
        mousemove_listener: google.maps.event.addListener map,
                                                  "mousemove", (e) => @handleMouseMove e

    if "ontouchstart" of window
      # Use touch events
      @setState
        touchmove_listener: google.maps.event.addListener map,
                                                  "mousemove", (e) => @handleTouchMove e

    @setState
      map: map

  componentWillUnmount: ->
    if @state.mousemove_listener?
      google.maps.event.removeListener @state.mousemove_listener

    if @state.touchmove_listener?
      google.maps.event.removeListener @state.touchmove_listener

  handleMouseDown: (e) ->
    # Mouse down event handler.

  handleMouseUp: (e) ->
    # Mouse up event handler.

  handleTouchStart: (e) ->
    # Touch start event handler.

  touchEndHandler: (e) ->
    # Touch end event handler.

  handleMouseMove: (e) ->
    # Mouse move event handler.

  handleTouchMove: (e) ->
    # Touch move event handler.

  render: ->
    <div style={ height: @props.height } onMouseDown={ @handleMouseDown }
         onMouseUp={ @handleMouseUp } onTouchStart={ @handleTouchStart }
         onTouchEnd={ @handleTouchEnd } />

高さのみ後から変更できるようにしたかったので,height プロパティを追加しています.lat, lng プロパティはマップ中心地点の緯度経度です.zoom などハードコーディングしているものも本当はプロパティ化すべきです.

イベントハンドラに関しては,DOM イベントは他の React コンポーネント同様に登録していますが,MouseMove イベントのみ,画面の x-y 座標ではなく地図上の緯度経度を取得するため Map API のイベントを使用しています.そのため,componentDidMount でイベントハンドラの登録と componentWillUnmount での登録削除が必要です.

また,タッチイベントも拾うようにしています.ただし,どこかで

React.initializeTouchEvents(true)

が必要です.

その他のコンポーネント

Marker や InfoWindow などはまた別の機会に.