経県値というアプリは知っていますか?各都道府県毎に、その地域で経験した内容を記録していくことで累計ポイントを獲得するアプリです。
今回はNCMBとMonacaを使って経県値風のアプリ(地図タップアプリ)を作ります。SVGを使って日本地図を表示し、経験したことをチェックしていきます。得点は出していませんが、ちょっとカスタマイズすればできるでしょう。
前回の記事では画面の説明とSDKの導入までを進めましたので、今回は匿名認証と地図表示を実装していきます。
コードについて
今回のコードはmemorymap-monacaにアップロードしてあります。実装時の参考にしてください。
匿名認証を有効にする
匿名認証とは、デバイスで生成したUUIDを使って認証を行う機能になります。自動生成した文字列なので、ユーザーがパスワードを入力したりする必要がなく、手軽に使えます。
管理画面のアプリ設定にして、匿名認証を有効化します。デフォルトでは無効なので注意してください。
匿名認証を利用する
匿名認証はアプリの起動時に利用するので js/app.js
にて実行します。NCMBを初期化した後、まずログイン判定を行います。これはログインユーザー情報を取得し、 null
判定を行うことで可能です。 null
ならばログインしていない状態です。
// ログインユーザーを取得
const user = ncmb.User.getCurrentUser();
// ログイン判定
if (!user) {
// ログインしていない場合は匿名ログイン
}
そしてログインしていない場合は以下のコードで匿名認証を実行します。たった1行のコードで認証処理が完了します。
// ログインしていない場合は匿名ログイン
await ncmb.User.loginAsAnonymous();
地図を表示する
ここからはNCMBは関係なく、D3.jsなどの話になります。まず必要なライブラリを www/index.html
にて読み込みます。位置情報を扱うためのD3 Geoなども読み込みます。
<script src="https://cdn.jsdelivr.net/npm/d3-array@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-geo@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js" integrity="sha512-4UKI/XKm3xrvJ6pZS5oTRvIQGIzZFoXR71rRBb1y2N+PbwAsKa5tPl2J6WvbEvwN3TxQCm8hMzsl/pO+82iRlg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
ファイルの作成
日本地図はD3.jsで日本地図を描き、都道府県別に色を塗る - Qiitaに沿って作成します。topojsonの最新版ではコマンドラインオプションが異なるため、1系をインストールしています。
できあがったファイル japan.json
は www/assets
以下に保存します。
ストアの作成
japan.json
で取得できる都道府県一覧は、一覧画面でも利用します。そこでストアを作成しておきます。これは www/js/stores.js
の内容です。
const createStore = Framework7.createStore;
const store = createStore({
state: {
prefectures: [],
},
getters: {
prefectures({ state }) {
return state.prefectures;
}
},
actions: {
setPrefectures({ state }, prefectures) {
state.prefectures = prefectures;
},
},
})
www/pages/map.htmlの処理
では画面を作成します。地図を表示するのは #map
になります。
<div class="page-content">
<svg id="map"></svg>
</div>
ここからはJavaScriptのコードです。画面がマウントされた際のイベント $onMounted
に実装します。
$onMounted(async () => {
await showMap();
});
showMap
関数では、まずD3.jsでの描画部分を作成します。地図データなので、緯度経度を使って中心を指定できます。
const showMap = async () => {
const map = document.querySelector('#map');
const width = map.clientWidth;
const height = map.clientHeight;
const svg = d3.select("#map");
const projection = d3.geoMercator()
.center([136, 35.5])
.scale(1000)
.translate([width / 2, height / 2]);
そして japan.json
から都道府県一覧を取得し、それをストアにも保存します。
const japan = await d3.json("../assets/japan.json");
pref = japan.objects.pref.geometries.map(d => d.properties.name_local);
$store.dispatch('setPrefectures', pref);
その pref
を使ってTopoJSONを作り、D3.jsで描画します。
const topo = topojson.feature(japan, japan.objects.pref).features;
const view = svg.selectAll(".pref")
.data(topo)
.enter()
.append("path")
.attr("class", function(d) {
return "pref pref" + pref.indexOf(d.properties.name_local);
})
.attr("d", path);
最後にズームイベント追加します。ただし、この実装では任意の場所をズームできず、使い勝手が悪いです。皆さんのアプリでは修正してください。
function zoomed() {
const transform = d3.zoomTransform(this);
this.setAttribute("transform", transform);
}
const zoom = d3.zoom()
.scaleExtent([1, 5])
.translateExtent([
[-10, -10],
[width + 90, height + 100]
])
.on("zoom", zoomed);
svg.call(zoom);
これで画面上に日本地図が表示されます。
まとめ
今回は匿名認証の実装と、アプリ画面に日本地図を表示するまでを実装しました。次回は地図をタップした際の処理、データ保存と取得を行います。