Nuxt.jsでGoogle Mapsを利用する

Google Maps利用するだけやしすぐ終わるやろと思っていましたが、少しはまってしまいました。 当たり前ですが、この手のものは利用時に最新情報拾っていくのが良いです。 (ここも含めて)その辺のブログを鵜呑みにせず、必ず公式見ましょう。
xkjyeah/vue-google-maps

f:id:rochefort:20210117171735p:plain

Installation

リポジトリ名と若干違ってややこしいのですが、 nuxtで利用できるvu2用のnpmは、 vue2-google-maps です。
これをnpm/yarnで入れるだけ。

Nuxt用設定

vue用として作られていますが、ご親切にnuxt用のQuickstartが記載されています。
基本はこの通りにやるだけです。
Quickstart (Webpack, Nuxt):

nuxt.config.js

公式とは順不同ですが、config設定してから開発入る方が、普通の流れなのでこちらから。

// nuxt.config.js
  build: {
    transpile: [/^vue2-google-maps($|\/)/]
  },

これだけで良いです。 build.extend() に書けと記載されていますが、今はtranspileに設定するだけで良いです。(PR出しておきました。)

VueGoogleMapsの設定

In your main.js or inside a Nuxt plugin: と記載がありますが、pluginに書く方が好みなので、そちらで。

// plugins/vue2-google-maps.js
import Vue from 'vue'
import * as VueGoogleMaps from '~/node_modules/vue2-google-maps'

Vue.use(VueGoogleMaps, {
  load: {
    key: process.env.YOUR_GOOGLE_API_KEY,
    libraries: 'places',
  },
})

基本設定はこれだけですが、地名のautocomplete用の設定などもあるようです。
 

plugins以下に書いたので、configに設定を追加します。

// nuxt.config.js
  plugins: [
    { src: '~/plugins/vue2-google-maps.js' }
  ],

GmapMapで描画

基本はこんな感じ。

<GmapMap
  :center="{lat:10, lng:10}"
  :zoom="7"
  map-type-id="terrain"
  style="width: 500px; height: 300px"
>
  <GmapMarker
    :key="index"
    v-for="(m, index) in markers"
    :position="m.position"
    :clickable="true"
    :draggable="true"
    @click="center=m.position"
  />
</GmapMap>

応用編

Reference

localでbuildしてから気づいたんだけど、exapmles/autoapi.html が用意されていてbuildするとapi documentが生成されます。
んでもって、以下にhostingされています。
http://xkjyeah.github.io/vue-google-maps/autoapi.html

Gmapオブジェクト

ref属性を指定しておけば、jsで扱えます。

      <GmapMap
        ref="gmap"
this.$refs.gmap

InfoWindow

Markerクリック時に吹き出しを表示するのに使えます。 Markerの子要素としても作れるみたいですが、クリック時に表示させるのは1つで良いので、今回は以下の様に実装。

  <GmapMarker
    :key="index"
    v-for="(shop, index) in shops"
    :position='{ "lat": shop.lat, "lng": shop.lng }'
    :clickable="true"
    :draggable="false"
    @click="toggleInfoWindow(shop)"
  />
  <GmapInfoWindow
    :options="map.infoWindow.options"
    :position="map.infoWindow.position"
    :opened="map.infoWindow.shown"
    @closeclick="map.infoWindow.shown=false"
  >

あとは、toggleInfoWindow で表示制御をするだけ。

fitBounds

Google MapsAPIには、複数Markerがある場合に、拡大率をいい感じに自動で設定してくれるfitBoundsというオプションがあるんだけど、これの使い方が分からず、結構ハマりました。
Maps JavaScript API  |  Google Developers

https://github.com/xkjyeah/vue-google-maps/blob/8d6bbac96b0797cf1e5b9537d58920c23ba75bd2/examples/components/02LatLngBounds.vue#L35
ここにexampleがあり、求めていたのこれこれと思って利用するも、動作せず。 どうも非同期読み込みのせいっぽい。
 

しばらくexampleを眺めている、 $gmapApiPromiseLazy() というそれっぽいやつがあることに気づきました。
https://github.com/xkjyeah/vue-google-maps/blob/8d6bbac96b0797cf1e5b9537d58920c23ba75bd2/src/components-implementation/autocomplete.js#L47
 

githubを検索すると、wikiがhit。
https://github.com/xkjyeah/vue-google-maps/wiki/vue-google-maps-FAQ#where-is-my-google

ということで、exampleに $gmapApiPromiseLazy() を利用する形で解決。

  watch: {
    shops(shops) {
      this.$gmapApiPromiseLazy().then(() => {
        if (shops.length > 2) {
          const bounds = new google.maps.LatLngBounds()
          for (let shop of shops) {
            bounds.extend({ "lat": shop.lat, "lng": shop.lng })
          }
          this.$refs.gmap.fitBounds(bounds)
        }
      })
    }
  },

Sodastream(Genesis v2)を購入しました

炭酸を月に1箱買う生活をこれまでしてきたのですが、ソーダ水メーカーが良いらしいと風の噂で聞いたので、正月にyoutubu観まくってメジャーなsodastream社の物を購入してみました。感想としては、なかなか良いです。水にもこだわりたくなってきます。

なんか今見たら、正月よりポイント還元率アップしててお得なようです。25%ぐらいポイント付くようです。

良い点

  • 炭酸量の調節ができる
    私は強炭酸好きじゃないので、強過ぎない程度に作れるのが良いです。
  • 毎月買わなくて良い
  • ペットボトル捨てなくて良い
  • (最初だけかもしれませんが)炭酸作るの結構楽しい

気になる点

  • ちょっとでかい
    youtubeで検索してもらえれば分かりますが、結構存在感あります。
  • シリンダーの交換が必要
    無くなったらシリンダーを交換が必要なのですが、公式だとお得便という2本x3回で12000円するやつが送料無料でお得なようです。 ですが、提携店舗(ソーダストリーム sodastream|お取扱店舗)に持ち込みができるようで、この場合は2000円でガス詰めてくれるみたいです。
    めっちゃ検索しにくいのですが、提携店舗も結構あるみたいなので、試してみようと思います。

検討内容

本体

いろいろ商品の種類があるようなんですが、本体のバリエーションは以下。
「①ガスの注入が自動か手動」、「②ボトルの着脱がワンタッチかクルクル回すか」、「③サイズが大きいか小さい」。

①ガスの注入が自動か手動
youtubuとかで見ると自動は便利そうなんですが、どうしても自分でpushして見たいので手動を選択。

②ボトルの着脱がワンタッチかクルクル回すか これもワンタッチが便利そうなんですが、若干値段差があったので、とりあえず安い方を選択。

③サイズが大きいか小さい 本当はサイズが小さい方が台所に置くには良さそうなのですが、主力商品ではなさそうなのと、シリンダーの交換頻度が上がりそうなので却下。

付属品

いろいろ付属品によって違うのですが、スターターキットと呼ばれる物だと本体+シリンダー+ペットボトル(1ℓ)+αで売られています。
でこの+α部分でつけておいた方が良いのが、付属のペットボトル(500ml)です。
炭酸は1ℓのペットボトルでも入れれるのですが、注入する量が多くなる(pushする回数が多区なる)ので、500mlのものがあると入れやすいです。
あと、私が買ったものは、シロップがついてましたが、別になくても良いです。(味はまぁまぁ美味しいですが、多いです。)

herokuのRailsアプリでDBをElephantSQLにしてみた

先日作成した、 Advent Calender Ranking 2020 のDBの話です。
DBはherokuのpostgres add-onを利用していたのですが、レコードの上限数(10000件)を超えてしまっていたため、数日で利用できなくなるアナウンスがありました。
f:id:rochefort:20210104224540p:plain

 
VPS立てるか、mongodbに移行しちゃうかを検討していたのですが、 DBのhostingサービスってもしかしたら、あるんじゃないかと探してみたら、 そのものズバリのサービスがありました。
ElephantSQL - PostgreSQL as a Service

ElephantSQL Pricing

f:id:rochefort:20210104225041p:plain こんな感じで、フリーだと20MBと割と小さめのDBでしか利用できませんが、とりあえず、 Advent Calender Ranking 2020 では事足りるので、利用してみました。

sign upして、planとregionを選ぶだけで、すぐ利用できました。

Region

ちなみに、Free枠でもいくつかRegionが選べました。 今回は、herokuに合わせています(後述)。
GCPやAzureも選べますし、AWSならtokyoもok。 この辺り、自前でRDSとかGCP建てずとも20MBまでなら無料で利用できるので、お得感あります。

HerokuのRegionの調べ方

herokuは無料だとAWSのus-east-1でした。

$ heroku info | grep Region
Region:         us
$ heroku regions --json | jq 'map(select(.name == "us"))'
[
  {
    "country": "United States",
    "created_at": "2012-11-21T20:44:16Z",
    "description": "United States",
    "id": "59accabd-516d-4f0e-83e6-6e3757701145",
    "locale": "Virginia",
    "name": "us",
    "private_capable": false,
    "provider": {
      "name": "amazon-web-services",
      "region": "us-east-1"
    },
    "updated_at": "2016-08-09T22:03:28Z"
  }
]

その他機能

フリープランだと、backupはコンソールから可能です。
slow queryが参照できる機能もあるのですが、設定が1ms以上になっており、フリーの場合は、ログの代わりに見てくれって感じなのかな。 あとmetricsの機能もあるようですが、フリーだと利用不可。

See Also

Advent Calender Rankingを作ってみた - rochefort's blog