Mapboxをカスタムフィールドで表示する方法


Mapboxとは

Mapboxは、世界中で採用されている地図サービスです。 地図の関する様々なプロダクトが展開されていて、中でもMapbox Studioは、独自の地図デザインを作成しwebサイト上に表示できるので、よりリッチなサイトを作成したい方にはぴったりなサービスとなっています。

今回は、そんなMapboxをユニットとして使用できるようにするまでの手順を紹介します。作業をすすめることで実際に表示することができるようになります。

a-blog cmsのバージョンは3.1.4で実装しています。バージョンによっては設定方法が異なる場合もございますのでご注意ください。

事前準備

a-blog cmsのカスタムユニットとしてMapboxを使用するためにMapbox側で準備するものが2つあります。

  1. アクセストークン:Mapboxと紐付ける為の値です。 MapboxのWebページでアカウントの作成を行うことで簡単に入手できます。
  2. スタイルURL:地図のデザインを取得する為のURLです。MapboxStudio(https://studio.mapbox.com/)というツールを使用して地図を作成しURLを取得することもできますが、今回は標準で使えるスタイルから好きなURLを選んでください。

※MapboxはAPIのライブラリを利用します。a-blog cmsで動作するための実装はGitHubに公開されているのでダウンロードしておいてください。

a-blog cmsの実装

まず必要な実装を確認します。 大まかな流れは以下の通りです。

  1. トークン/スタイルURLを入力するブログのカスタムフィールドを作成
  2. エントリー編集画面を作成
  3. 表示側エントリーのHTML作成

※(1), (2)は管理画面で、(3)は表示側の設定です。

トークン/スタイルURLを入力するブログのカスタムフィールドを作成

MapboxのトークンとスタイルURLは、サイト全体で共通して扱う情報になるかと思うので、ブログのカスタムフィールドから設定できるようにしていきます。 以下のコードを /themes/利用中のテーマ/admin/blog/field.html に追加してください。

<h3 class="acms-admin-admin-title2">Mapboxアクセストークン登録</h3>
<table class="adminTable acms-admin-table-admin-edit">
	<tr>
		<th><label for="input-text-mapbox_accesstoken">アクセストークン</label><i data-acms-tooltip="アクセストークンを設定します。" class="acms-admin-icon-tooltip js-acms-tooltip-hover"></i></th>
		<td>
			<input type="text" name="mapbox_accesstoken" value="{mapbox_accesstoken}" id="input-text-mapbox_accesstoken" class="acms-admin-form-width-large" />
			<input type="hidden" name="field[]" value="mapbox_accesstoken" />
		</td>
    </tr>
    <tr>
		<th><label for="input-text-mapbox_styleurl">スタイルURL</label><i data-acms-tooltip="スタイルURLを設定します。" class="acms-admin-icon-tooltip js-acms-tooltip-hover"></i></th>
		<td>
			<input type="text" name="mapbox_styleurl" value="{mapbox_styleurl}" id="input-text-mapbox_styleurl" class="acms-admin-form-width-large" />
			<input type="hidden" name="field[]" value="mapbox_styleurl" />
		</td>
	</tr>
</table>

すると、以下のように入力欄が表示されるので、事前に準備しておいたアクセストークンとスタイルURLを入力し、保存しておいてください。



エントリー編集画面を作成

ここでは、エントリー編集画面でMapboxを表示していきます。 そのためにMapboxを表示したいエントリーを決めないといけません。今回は、「地図」カテゴリーに所属するエントリーにMapboxを表示できるようしていきましょう。

「地図」カテゴリーを作成してください。



次はエントリー編集画面です。 カスタムフィールドを使ってMapboxを表示させるため、/themes/利用中のテーマ/admin/entry/field.html に以下のコードを追加して「地図」カテゴリーのみに適応されるようにします。 ファイルがなければ作成してください。

@include("/admin/entry/ccd/%{CCD}.html")

そして、/themes/利用中のテーマ/admin/entry/ccd/map.html を作成し以下のコードを追加します。

<!-- Maboxライブラリ読み込み -->
<script src='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css' rel='stylesheet' />
 
<!--Mapbox Geocoderの読み込み 検索フォームに入力した場所の位置を取得 -->
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet"
    href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.css"
    type="text/css" />
 
<script src="/js/mapboxfield.js"></script>
<!-- Mapboxライブラリ読み込み ここまで-->
 
<!-- BEGIN_MODULE Blog_Field -->
<!-- 管理画面>ブログ>カスタム設定に入力した値の呼び出し -->
<div id="accesstoken_styleurl" data-accesstoken="{mapbox_accesstoken}" data-styleurl="{mapbox_styleurl}"></div>
<!-- END_MODULE Blog_Field -->
 
<!-- 地図が挿入される -->
<div id='fmapwrapper' style="width: 820px; height: 320px; max-width: 100% ; margin-left: auto; margin-right: auto;">
    <div id='fmap' style='width: 820px; height: 80%; max-width: 100%;' data-lat="{fmapbox-lat}" data-lng="{fmapbox-lng}"
        data-zoom="{fmapbox-zoom}" data-pitch="{fmapbox-pitch}" data-bearing="{fmapbox-bearing}"
        data-mapsize="{fmapbox-mapsize}" data-maptype="field">
    </div>
    <!-- 地図の検索ボックス -->
    <div id="geocoder" style="width: 100%; height: 45px;" class="geocoder"></div>
</div>
 
<!-- BEGIN_MODULE Touch_Edit -->
<table class="acms-admin-table-admin-edit">
    <tr>
        <th>経度</th>
        <td>
            <input id="lng" type="text" name="fmapbox-lng" value="{fmapbox-lng}" class="acms-admin-form-width-full" />
            <input type="hidden" name="field[]" value="fmapbox-lng" />
        </td>
    </tr>
    <tr>
        <th>緯度</th>
        <td>
            <input id="lat" type="text" name="fmapbox-lat" value="{fmapbox-lat}" class="acms-admin-form-width-full" />
            <input type="hidden" name="field[]" value="fmapbox-lat" />
        </td>
    </tr>
    <tr>
        <th>ズーム</th>
        <td>
            <input id="zoom" type="text" name="fmapbox-zoom" value="5" class="acms-admin-form-width-full" />
            <input type="hidden" name="field[]" value="fmapbox-zoom" />
        </td>
    </tr>
    <tr>
        <th>角度</th>
        <td>
            <input id="pitch" type="text" name="fmapbox-pitch" value="{fmapbox-pitch}"
                class="acms-admin-form-width-full" />
            <input type="hidden" name="field[]" value="fmapbox-pitch" />
        </td>
    </tr>
    <tr>
        <th>回転</th>
        <td>
            <input id="bearing" type="text" name="fmapbox-bearing" value="{fmapbox-bearing}"
                class="acms-admin-form-width-full" />
            <input type="hidden" name="field[]" value="fmapbox-bearing" />
        </td>
    </tr>
</table>
<!-- END_MODULE Touch_Edit -->

これで「地図」カテゴリーに所属するエントリーに、Mapboxが表示されるようになったかと思います。 確認してみましょう。



表示側エントリーのHTML作成

最後に表示側のエントリーです。 /themes/利用中のテーマ/include/field/entry/field.html を作成し、以下のコードを追加してください。

@include("/include/field/entry/ccd/%{CCD}.html")

そして、/themes/利用中のテーマ/include/field/map.html を作成し、以下のコードを追加してください。

<!-- Maboxライブラリ読み込み -->
<script src='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css' rel='stylesheet' />
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet"
    href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.css"
    type="text/css" />

<script src="/js/mapboxfield.js"></script>

<!-- BEGIN_MODULE Blog_Field -->
<!-- 地図作成のためのアクセストークンとスタイルURL -->
<div id="accesstoken_styleurl" data-accesstoken="{mapbox_accesstoken}" data-styleurl="{mapbox_styleurl}"></div>
<!-- END_MODULE Blog_Field -->

<div id='fmapwrapper' style="width: 820px; height: 320px; max-width: 100% ;">
    <div id='fmap' style='width: 100%; height: 100%; max-width: 100%;' data-lat="{fmapbox-lat}" data-lng="{fmapbox-lng}"
        data-zoom="{fmapbox-zoom}" data-pitch="{fmapbox-pitch}" data-bearing="{fmapbox-bearing}"
        data-styleurl="{fmapbox_styleurl}" data-comment='{fmapbox-comment}' data-mapsize="{fmapbox-mapsize}"
        data-maptype="show">
    </div>
</div>

これでカテゴリーがmapの時にファイルが読み込まれるようになるました。 それでは、/themes/利用中のテーマ/map/entry.htmlを作成し、Entry_Bodyを貼り付け、以下の箇所(ユニットの上)にカスタムフィールドを読み込んでください。

※a-blog cms標準のテーマをご利用の方は、別カテゴリーのentry.htmlをコピーしてきた方が、デザインの統一ができることとカスタムフィールドを読み込むインクルードも記載されていると思うので、勝手がいいと思います。

<div>
	<!-- ここにカスタムフィールドを読み込む -->
	@include("/include/entry/field.html")
	<!--  -->

	<!-- BEGIN unit:veil -->
	<div class="acms-entry">
		<div class="acms-grid-r">
		@include("/include/unit.html")
		</div>
	</div>
	<hr class="clearHidden">
	<!-- END unit:veil -->

以上が、カスタムフィールドでMapboxを表示する方法です。 最後にエントリーを確認してみてください。



Mapboxを安全に使用する方法

本実装ではMapboxのアクセストークンが開発者ツールを通じて見られるようになっています。本番環境での使用の際には以下のリンクの内容に従い、URL制限の有効化を行ってください。URL制限を追加したトークンは指定URLから発信されたリクエストのみ処理をするため、Webアプリのアクセス・トークンをよりセキュアにする事が可能です。

Mapboxを安全に使用する

次世代フロントエンドツール「Vite」を a-blog cms で利用するためのコツ

Vite

Vite(ヴィート)


この記事は Advent Calendar 2023 の24日目の記事となります。a-blog cms にまつわる25日分の記事が公開されていますので、是非ご覧ください。 https://adventar.org/calendars/8651

a-blog cms の テーマのビルド環境

a-blog cms 標準テーマのビルド環境は、これまで「webpack」を利用してビルドされていました。パッケージに入っている「omake」ディレクトリ内にある、ビルド系ファイルを自分のテーマに持ってくることで、webpack環境を利用できるようになっておりまます。ただ近年は「webpack」以外にもモダンなビルドツールが出てきましたので、今回は「Vite」というツールについてa-blog cmsで使用するためのコツを紹介したいと思います。


omakeディレクトリにあるビルド系ファイル

omakeディレクトリにあるビルド系ファイル


Viteとは?

公式サイト(https://ja.vitejs.dev/

詳しくは公式サイトをご覧ください。従来のビルドツールに比べ、パフォーマンスに特化しているツールになっています。

この記事では、Viteの使い方や設定方法にはフォーカスせず、a-blog cms で利用する場合の設定方法やコツをご紹介します。

バックエンドとの統合

a-blog cmsのようにバックエンドがHTMLを配信するシステムの場合、少し工夫が必要です。 WordPressや、Rails、Laravelのような有名CMS・ライブラリの場合、プラグインが用意されておりプラグインを導入することにより、Viteとの統合が出来るようになっております。

公式サイト「バックエンドの統合」

a-blog cms で Viteを利用できるようにする

a-blog cms で Viteを利用できるようにします。まずは「vite.config.js」を調整します。

「build」オプションで、「manifest」を「true」に設定し、「input」でエントリーポイントとなるjs(themes/xxxx/src/js/main.js)を指定します。

build: {
  manifest: true, // dist に manifest.json を出力
  rollupOptions: {
    input: {
      bundle: resolve(__dirname, 'src/js/main.js'),
    },
  },
},

この設定をすることで、manifest.jsonにビルドされたアセットのパスが出力されるようになります。

manifest.jsonの例

{
  "main.js": {
    "file": "assets/main.4889e940.js",
    "src": "main.js",
    "isEntry": true,
    "dynamicImports": ["views/foo.js"],
    "css": ["assets/main.b82dbe22.css"],
    "assets": ["assets/asset.0ab0f9cd.png"]
  },
  "views/foo.js": {
    "file": "assets/foo.869aea0d.js",
    "src": "views/foo.js",
    "isDynamicEntry": true,
    "imports": ["_shared.83069a53.js"]
  },
  "_shared.83069a53.js": {
    "file": "assets/shared.83069a53.js"
  }
}

この書き出された「manifest.json」の情報を使って、JSをHTMLに読み込みます。

専用モジュールの用意

上記で出力された「manifest.json」の情報をHTMLに出力するためのモジュールを作成します。

extension/acms/GET/Vite.php」を作成して、以下コードを貼り付けてください。

<?php

namespace Acms\Custom\GET;

use ACMS_GET_Json_2Tpl;
use Template;
use ACMS_Corrector;

class Vite extends ACMS_GET_Json_2Tpl
{
    public function get()
    {
        $tpl = new Template($this->tpl, new ACMS_Corrector());

        try {
            if (isset($_ENV['VITE_MODE']) && $_ENV['VITE_MODE'] === 'develop') {
                $vars['localhost'] = isset($_ENV['VITE_LOCALHOST']) ? $_ENV['VITE_LOCALHOST'] : 'http://localhost:5173';
            } else {
                $json = $this->getManifest('themes/'.$_ENV['VITE_BUILD_THEME'].'/dist/manifest.json');
                $vars = json_decode($json, true);
                if (is_array($vars) && $this->is_vector($vars)) {
                    $vars = [
                        'root' => $vars,
                    ];
                }
            }
            if (is_array($vars)) {
                return $tpl->render($vars);
            }
        } catch (\Exception $e) {
            if (DEBUG_MODE) {
                throw $e;
            }
        }
        return '';
    }

    protected function env($key, $default = '') {
        return isset($_ENV[$key]) ? $_ENV[$key] : $default;
    }

    protected function getManifest($path)
    {
        try {
            $manifest = @file_get_contents($path);
            if (empty($manifest)) {
                throw new \RuntimeException('Empty Manifest.');
            }
        } catch ( \Exception $e ) {
            return '';
        }
        return $manifest;
    }
}

HTMLテンプレートの修正

モジュールが作成できたら、JSを読み込むインクルードファイルを修正します。以下のように作成したモジュールを使って読み込んでください。

ポイントは、 で、ここは vite.config.js で指定したエントリポイントに合わせて変更ください。

<!-- BEGIN_MODULE Vite -->

<!-- BEGIN src/js/main.js -->
<script type="module" src="/dist/{file}" async></script>
<!-- END src/js/main.js -->

<!-- BEGIN develop -->
<script type="module" src="{localhost}/@vite/client"></script>
<script type="module" src="{localhost}/src/js/main.js"></script>
<!-- END develop -->

<!-- END_MODULE Vite -->

.envファイルの修正

.envファイルに以下を追記してください。

VITE_MODE=develop # develop | production
VITE_LOCALHOST=http://localhost:5173 # http://localhost:5173
VITE_BUILD_THEME=hoge # ビルド対象テーマを指定します

使用方法

ここまでで下準備は完了です。使い方ですが本番用ビルドをする場合と、開発ビルドを行う場合の2通りがあります。 普段開発するときは開発ビルドを行いファイル保存と同時にビルドが走らせてスムーズな開発を行います。本番環境にアップロードする場合は本番用のビルドを行います。

開発ビルド

「vite」コマンドを実行すると開発サーバーが立ち上がり、カーカルURLが表示されます。このURLを覚えていてください。

  VITE v4.4.7  ready in 523 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h to show help

次に、「.env」ファイルを修正します。

VITE_MODE=develop # developを指定
VITE_LOCALHOST=http://localhost:5173 # 先ほど覚えたURLを指定
VITE_BUILD_THEME=yomeruba-v2 # ビルド対象テーマを指定します

以上で、a-blog cms と Vite によるアセット配信が統合されるようになります。

本番用ビルド

「vite build --mode=production」コマンドを実行するとプロダクションビルドを行えます。 プロダクションビルドされたファイルを反映する本番環境の「.env」ファイルを以下のように修正します。

VITE_MODE=production # productionを指定
VITE_LOCALHOST=http://localhost:5173 # 適当な値で大丈夫です
VITE_BUILD_THEME=hoge # ビルド対象テーマを指定します

以上で、a-blog cms と Vite によるアセット配信が統合されるようになります。

以上となります。

フロントエンドツールを使っている方はぜひ試してみてください。