前提・実現したいこと
reactの学習として、地図操作ページを作成中。
react + mapbox-gl で、『最後にクリック(またはダブルクリック)した場所にだけ、マーカーが表示される』ようにしたい
……地図クリック時の内部動作としては、
①それまで表示していたマーカーを削除
↓
②クリックした場所にマーカーを作成
↓
③作成したマーカー情報を(次に地図がクリックされた時に削除するため)保存
を、考えています。
該当のソースコード
地図の表示は
https://qiita.com/KamataRyo/items/f3e59d61ca19d61e31e8
を参考に、
JavaScript:App.js
1import React, { Component } from 'react'; 2import './App.css'; 3 4import mapboxgl from 'mapbox-gl'; 5mapboxgl.accessToken = 'アクセストークン情報'; 6 7// Appコンポーネント 8class App extends Component { 9 10 mapstyle = { 11 width:"800px", 12 height:"300px", 13 backgroundColor:"red" 14 } 15 btnStyle = { 16 fontSize:"20pt", 17 padding:"0px 10px" 18 } 19 20 constructor(props){ 21 super(props); 22 this.state = { 23 marker: []/* ←「③」用の、マーカー情報保存用の枠 */ 24 } 25 26 this.moveMap = this.moveMap.bind(this); 27 this.makePin = this.makePin.bind(this); 28 this.componentDidMount = this.componentDidMount.bind(this); 29 } 30 31 componentDidMount() { 32 this.mapbox = new mapboxgl.Map({ 33 container: this.container, 34 style: 'mapbox://styles/mapbox/streets-v11', 35 /* 地図の初期緯度経度[lng,lat] */ 36 center: [139.72116702175174, 35.64997652994234], 37 /* 地図の初期ズームレベル */ 38 zoom: 8 39 }) 40 41 var marker = new mapboxgl.Marker(); 42 marker.setLngLat([139.72116702175174, 35.64997652994234]); 43 marker.addTo(this.mapbox); 44 45 this.setState((state) => ({ 46 marker: marker 47 })) 48 49 var map = this.mapbox 50 51 this.mapbox.on('dblclick', function(e) { 52 53 //↓↓↓※1↓↓↓ 54 var newMarker = new mapboxgl.Marker(); 55 newMarker.setLngLat([e.lngLat.lng, e.lngLat.lat]); 56 newMarker.addTo(map); 57 //↑↑↑※1↑↑↑ 58 59 }); 60 } 61 62 makePin(e) { 63 //↓↓↓※2↓↓↓ 64 // それまで表示していたピンを削除する 65 this.state.marker.remove(); 66 //↑↑↑※2↑↑↑ 67 68 } 69 70 moveMap(e) { 71 //↓↓↓※3↓↓↓ 72 // それまで表示していたピンを削除する 73 this.state.marker.remove(); 74 75 // (クリックしたボタンから取得した)座標情報を元にマーカーを作成 76 var marker = new mapboxgl.Marker(); 77 marker.setLngLat([e._targetInst.memoizedProps.lat, e._targetInst.memoizedProps.lon]); 78 marker.addTo(this.mapbox); 79 80 // 作成したマーカー情報を保存 81 this.setState((state) => ({ 82 marker: marker 83 })) 84 //↑↑↑※3↑↑↑ 85 86 } 87 88 render() { 89 return( 90 <div> 91 MAP 92 {/* //↓↓↓※2↓↓↓ */} 93 <div style={this.mapstyle} className={'map'} onClick={this.makePin} ref={e => (this.container = e)}></div> 94 {/* //↑↑↑※2↑↑↑ */} 95 96 {/* //↓↓↓※3↓↓↓ */} 97 <button onClick={this.moveMap} lat='139.767036' lon='35.680865'>東京</button> 98 <button onClick={this.moveMap} lat='139.758153' lon='35.666397'>新橋</button> 99 <button onClick={this.moveMap} lat='139.74015' lon='35.629867'>品川</button> 100 {/* //↑↑↑※3↑↑↑ */} 101 102 </div> 103 ) 104 } 105} 106 107export default App;
試したこと、発生した問題
######『※1』の部分
『componentDidMount』内で作成したダブルクリックイベントで、『ダブルクリックした地点の座標情報』を取得
↓
取得した座標でマーカーを作成
【問題……『※1』の前後で、(『*3』でやっているように)『this.state.』『this.setState』でstate情報を参照,設定しようとするとエラー】
・this.state.marker.remove()→エラーメッセージ:「TypeError: Cannot read property 'marker' of undefined」
・this.setState(……→エラーメッセージ:「TypeError: this.setState is not a function」
######『※2』の部分
地図を表示しているdiv要素をクリックした時、クリックイベント(makePin)を発生させる
↓
今まで保存していたマーカー情報をstateから取得し、それを削除
【問題……『※1』とは異なり、『クリックした地点の座標情報』の取得方法が見つけられないので新たなマーカーを作れない(『e.〇〇.☓☓』で座標は取得可能なのでしょうか)】
なお『※1』でダブルクリックイベント、『※2』でクリックイベントにしているのは、動作検証時にどちらが発生しているか確認するため(それ以外に特に意味はない)です。
######『※3』の部分
『※2』でもし『クリックした地点の座標情報』を取得出来たなら、他は問題なく動作することを検証
……地図クリックの代わりに『東京』『新橋』『品川』の座標情報を持ったボタンをクリック→今まで表示されていたマーカーを削除し、代わりにボタンが示している地点にマーカーが作成されることを確認。
知りたいこと
・『※1』のように『componentDidMount』内で作成したイベント内で『state』を使用する方法
または
・『※2』のイベント内で【地図のクリックされた座標】を取得する方法
……また、もしどちらの方法もあるとすれば、『※1』『※2』どちらのやり方が一般的なのでしょうか。
あなたの回答
tips
プレビュー