0
0

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 3 years have passed since last update.

jsフレームワークstimulusでyahoo地図を操作してみた(その四、最終回)

Posted at

やったこと、やる予定のこと

0. railsアプリへのstimulus適用

1. stimulusでyahoo地図を表示

2. 表示した地図上で、指定座標に移動

3. 住所から座標を取得し、それをDBに登録(前回)

4. 「3」で登録した情報を選択し、yahoo地図上でその場所に移動(←今ここ)

だいぶ間が空いてしまいましたが、最終回。
一覧画面にて、
【「3」で登録した座標情報を選択→その地図の場所に移動】
をできるようにします。

##まずは、一覧画面にて地図を表示
今回は、作成するjsファイルの名称は「index_map_controller.js」にしました
(この場合、html側の名称は「index-map」にする必要あり……詳しくはこちらを参照)。

app/views/maps/index.html.erb
<!-- 「data-controller」開始 -->
<div data-controller="index-map">

  <!-- 中略 -->

  </table><!-- ←scaffoldで自動作成される「table」の終了 -->

  <!-- これで地図を表示 -->
  <div id="map" style="width:800px; height:400px"  data-target="index-map.map" ></div>

</div>
<!-- 「data-controller」終了 -->

前回・前々回と同様の、地図表示。
ただし今回は、
 a.地図の中心点表示なし
 b.縮尺変更用のスライドバー表示
 c.マウスのスクロールホイールでも地図縮尺変更可能
としています。

app/javascript/controllers/index_map_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "map"]

  initialize() {

       this.map = new Y.Map(this.mapTarget.id,{configure : {

     // ↓【c.マウスのスクロールホイールでも地図縮尺変更可能】
         scrollWheelZoom : true

       }});

       this.map.drawMap(new Y.LatLng(0, 0), 17, Y.LayerSetId.NORMAL);

    // ↓【a.地図の中心点表示なし_1】
       // var center = new Y.CenterMarkControl

       var control = new Y.LayerSetControl();

    // ↓【a.地図の中心点表示なし_2】
       // this.map.addControl(center);

       this.map.addControl(control);

    // ↓【b.縮尺変更用のスライドバー表示】
       var sliderzoom = new Y.SliderZoomControlVertical();
       this.map.addControl(sliderzoom);

  }
}

このへんの細かな地図表示方法については、こちら
……とYOLP公式頁を覗いてみたら、「API提供終了のお知らせ」って、マジか!!!

…………………………………………まあ、気を取り直して。

##次に、一覧画面のレコードごとに「押したらその場所に移動するボタン」を設置します

app/views/maps/index.html.erb

  <tbody>
    <% @maps.each do |map| %>
      <tr>
        <!-- 中略 -->
        <td><%= link_to 'Destroy', map, method: :delete, data: { confirm: 'Are you sure?' } %></td>

        <!-- ↓scaffoldで自動作成されている「レコード削除」の後ろに、追記 -->
        <!--  →「@maps」に格納されているレコード数だけ、ボタンも作られる。 -->
        <td><input type="button" value="移動" data-action="click->index-map#move" data-lat = <%= map.latitude %>  data-lon = <%= map.longitude %> ></td>

      </tr>
    <% end %>
  </tbody>

ボタンの「data-action」設定
  →クリックしたらjs側で「move」メソッドを走らせる

また↑の「move」メソッド内で、そのレコードの位置情報(経度、緯度)を使いたいので、
それも**「data-〇〇」形式で**ボタンに持たせてやります(この場合は、「data-lat」と「data-lon」)。

##最後に、js側で地図を移動する動き=「move」メソッドを記述する。
これは、かんたん
……html側にて「data-〇〇=」で設定した値は、js側では「el(アクション対象を引数として取得).target.dataset.〇〇」で取得できるので、

app/javascript/controllers/index_map_controller.js
  move(el){
    var current_location = new Y.LatLng(el.target.dataset.lat,el.target.dataset.lon);
    this.map.panTo(current_location, true);
  }

取得した緯度、経度を「current_location」に放り込み、それをmapの「panTo」に与えてやればいいわけです(この場合は「current_location」なんて作らずに、一行で記述しても良かったかも)。

これで、
スクリーンショット 2020-04-17 18.29.01.png
「移動」ボタンを押すとその場所に地図上を移動できるようになります。

##おまけで、ピンを立ててみる。
移動できるのはいいけど、そのレコードの位置情報がどこを指しているのかが若干分かりにくい
──ということで、登録されているレコードの場所にははじめ(画面ロード時)から📍が立っていることにしてみます。

画面ロード時に📍を立てるには、【js側のinitializeメソッド内】で【全レコードの位置情報】を取得する必要があります。

そこでhtml側では「移動」ボタンに、

app/views/maps/index.html.erb
<td><input type="button" value="移動" data-action="click->index-map#move" data-lat = <%= map.latitude %>  data-lon = <%= map.longitude %> <%# これ追記→ %>data-target="index-map.pin" <%# ←これ追記 %> > ></td>

と、【お前は『pin』というdata-targetだ!】という記述を追加してやります。

ただ、この「移動」ボタンはレコード数だけあるので、【『pin』というdata-target】もレコード数だけ存在します。

……さっきも出した
スクリーンショット 2020-04-17 18.29.01.png
 ↑の場合、
「大洗」「銚子」「焼津」「境港」それぞれのボタンが【『pin』というdata-target】となっています。

この複数ある【target】は、js側では【targets】として纏めて取得することができます。

↓は画面ロード時、【js側のinitializeメソッド】の途中でストップさせたコンソール画像
  登録されているレコードは、上に貼った画像と同じ「大洗」「銚子」「焼津」「境港」です。
スクリーンショット 2020-04-17 18.53.58.png
this.pinTargets → 4つのボタン全てをターゲットとして取得
this.pinTargets[0] →そのうち1つ目、「大洗」のボタンをターゲットとして取得

「座標情報を持ったターゲット」の取得目処がついたので、
あとは取得したターゲット分だけ、地図に📍を立ててあげます。

app/javascript/controllers/index_map_controller.js
  initialize(){

    //地図を表示する記述……中略

    var map_box = this.map;

    this.pinTargets.forEach(function(pin){
      var current_location = new Y.LatLng(pin.dataset.lat,pin.dataset.lon);
      var marker = new Y.Marker(current_location);
      map_box.addFeature(marker);
    });
  }

これで
・地図の「登録された場所」全てにピンが立ち、
・レコードを選択すれば「その登録地点に地図が移動」
するようになります。

サンプルコードはscaffoldで作った一覧なので見栄えがいまいちですが、レイアウトを整えて画像登録と組み合わせれば

  ● 東海道五十三次

  ● シン・ゴジラ、進撃経路(パスワードは「sin」と入力してみてください)

なんてものも作れるようになります。

なんですが…………………………………………
メインで使っていたAPI、Yahoo! JavaScriptマップAPIが2020年10月末で提供終了予定。
代替サービスは紹介されてるけど──無料プランだとアクセス数その他、色々制約がありそうです orz。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?