まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

業務やプライベートでウェブアプリを作る際に colorbox を使う機会が少なからずあります。jQuery に対応したモーダルダイアログの軽量プラグインで、メイン画面にオーバーラップするダイアログ画面を呼び出し、ダイアログを閉じるまではメイン画面が使えなくなります。HTML 的な言い方をすると、ボックス領域の表示/非表示を切り替えつつ、ここが表示されている間は他の要素にアクセスできなくさせたい場合などに便利です。

加えて、個人的によく Google MAPs API を使った地図アプリを作っています。他にも多くの地図 API はありますし、実際に使うこともありますが、ストリートビューなど他にはない機能もあって、マンホールマップを始め、多くのアプリで Google MAPs API を活用しています。

今回紹介するのはこの2つを組み合わせて使う方法、つまり colorbox のモーダルダイアログ内で Google MAPs の地図を表示する方法です。特に考慮することなく普通に(colorbox で表示する領域の中に Google MAPs の地図領域を定義しておくだけで)使えそうな気がしていたのですが、どうもこれらの初期化処理時における相性があまりよくないようで、ちょっとしたコツが必要だということがわかりました。

この「ちょっとしたコツ」の結論は
・colorbox のダイアログを表示して、
ダイアログの表示が完了した後で Google MAPs を初期化してダイアログ内に表示する
という順序で実現する必要がありそうでした。一般的には HTML ページの初期化時に Google MAPs を初期化することが多いと思うのですが、colorbox と組み合わせて使う場合は、その初期化タイミングをダイアログの表示後に(ダイアログの表示が完了したことを検知した上で動的に)行う必要がありそうでした。


以下は具体的な実現方法です。まず jQuery や colorbox、Google MAPs API の JavaScript や CSS を一通りロードします(Google MAPs API をロードする際に API KEY の取得と指定が必要です):
  :
<script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript" src="//maps.google.com/maps/api/js?key=(your api key)"></script>
<link href="/css/colorbox.css" rel="stylesheet"/>
<script src="/js/jquery.colorbox-min.js" type="text/javascript"></script>
  :

HTML 内に colorbox で表示するモーダルダイアログ部分(id="mapModal")を定義します。ここは初期状態では表示されていてはまずいので display:none のスタイル指定をしておきます。またモーダルダイアログ表示した際にこの id="map_canvas" のブロックの中で Google MAPs の地図を表示することになりますが、初期段階では何も定義しません:
  :
<div style="display:none">
  <div id="mapModal">
    <div id="map_canvas" style="width:100%; height:520px"></div>
  </div>
</div>
  :

ではこのブロックをモーダルダイアログ表示するための colorbox のアクションを作成します。以下の例では <span> で括られたエリア(id="span1")をクリックした時に colorbox のモーダルダイアログを 90% x 90% でインライン表示するようにしています。加えてこのモーダルダイアログが表示されきった直後に $('#map_canvas').modalMap() が実行されるように定義しています:
  :
<span href="#mapModal" id="span1">ここをクリック</span>

<script>
$(function(){
  $('#span1').colorbox({
    inline: true,
    transition: 'none',
    width: '90%',
    height: '90%',
    onComplete: function(){
      $('#map_canvas').modalMap();
    }
  });
});
</script>
  :

↑この時の <span> 要素に href 属性を付けて対象モーダルの id を指定するのが肝のようです。。

最後にこの modalMap() 関数を定義して、この中で動的に Google MAP を初期化して表示するまでのコードを記述します:
  :
<script>
$.fn.modalMap = function(){
  var latlng = new google.maps.LatLng( 35.690625, 139.699788 );
  var opt = {
    zoom: 8,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scaleControl: true
  };

  var map = new google.maps.Map( document.getElementById( 'map_canvas' ), opt );
  map.setCenter( latlng );

  var marker = new google.maps.Marker({
    position: latlng,
    map: map
  });
};
</script>
  :

これで <span> 部分をクリックすると colorbox のモーダルダイアログを出し、ダイアログ内で動的にGoogle MAP の地図を初期化&表示する、という一連のコードが完成です:
2019090801

  ↓

2019090802

(↑わかりにくいかもしれませんが、地図部分はモーダルダイアログ表示されています)



CentOS 7 で運用する独自ドメインのウェブサーバーを Certbot(Let's encrypt) で無料の証明書を取得して SSL 化しました。その手順の備忘録です:
le-logo-standard



【環境】
OS: CentOS 7.6(64bit)
HTTP: Apache HTTPD 2.4.6※

※正確には WordPress 5.2.2(ja) を MariaDB 5.5.60 で運用中。Apache と MariaDB は yum で導入、WordPress は公式サイトから最新版 latest-ja.tar.gz を取得して展開

Document Root: /var/www/html/wordpress
ドメイン名(仮): mydomain.com (DNS 設定済み)

1サーバーで1ドメイン運用、のシンプルなケースを想定しています。http では既に稼働中、という状態だと思ってください。


【準備】

Certbot のインストール
$ sudo yum install -y epel-release
$ sudo yum install -y certbot python-certbot-apache

root で動作確認
$ sudo -i
# certbot --version
certbot 0.36.0

certbot コマンドを実行し、バージョン番号が表示される(=インストールされている)ことを確認します。

【作業】

以下のコマンドを実行するにあたり、証明書を導入するサーバーに HTTP(TCP/80) および HTTPS(TCP/443) でパブリック・アクセスできるようにポート設定できているものとします。またDocument Root に Basic 認証などがかかっている場合は外しておきます(必須)。

証明書作成
# certbot certonly --webroot -w /var/www/html/wordpress -d mydomain.com

-w オプションで DocumentRoot、-d オプションでドメイン名を指定します。E メールアドレスの入力を求められるので自分のメールアドレスを入力して Enter 、そして利用規約に A(Agree) を押して、最後に N(No) を押します:
# certbot certonly --webroot -w /var/www/html/wordpress -d mydomain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): myname@xxx.co.jp
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

処理が成功すると以下のような "Conguratulations!" というメッセージが表示されます:
2019082900


ここまで完了していると、以下の4ファイルが作成されているはずです(mydomain.com 部分には指定したドメイン名が入ります):
  1. /etc/letsencrypt/live/mydomain.com/cert.pem (サーバー証明書(公開鍵))
  2. /etc/letsencrypt/live/mydomain.com/chain.pem (中間証明書)
  3. /etc/letsencrypt/live/mydomain.com/fullchain.pem (サーバー証明書と中間署名書の結合ファイル 今回は使いません
  4. /etc/letsencrypt/live/mydomain.com/privkey.pem (秘密鍵)

証明書を有効にする

/etc/httpd/conf.d/ssl.conf ファイルの以下3箇所を書き換えて&コメントを外すなどして有効にします:
  • SSLCertificateFile /etc/letsencrypt/live/mydomain.com/cert.pem
  • SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem
  • SSLCertificateChainFile /etc/letsencrypt/live/mydomain.com/chain.pem
  • (fullchain.pem は使わない)

また、Basic 認証をかける場合はこのタイミングで元に戻して(有効にして)おきます。

HTTP サーバーを再起動
# systemctl restart httpd


以上です。僕が以前にウェブサーバーやそのアプリケーションを大量に作る仕事していた頃は無料で証明書作ってもらえるサービスはなくて、いわゆる「オレオレ証明書」に頼っていたのでした。改めていい時代になりました。


OpenStreetMap とその API を使って簡易ドライブゲームを作って公開しました。

OpenStreetMap は誰でも無料&自由に使える地図や地理情報のオープンデータプロジェクトです。API も公開されており、位置情報アプリケーション開発時に利用することができます:
2019081707


この OpenStreetMap API を使ってドライブゲームを作って公開してみました。GitHub リポジトリはこちらです:
https://github.com/dotnsf/openmap_drive/

2019081708


実質的に index.html ファイル1つだけのプロジェクトなので GitHub Pages で公開もしています。実際に遊ぶには PC のブラウザでこちらを参照してください:
https://dotnsf.github.io/openmap_drive/

2019081702


パラメータを付けずにアクセスすると、デフォルトで三重県鈴鹿市の鈴鹿サーキットのメインストレートの一部が OpenStreetMap でブラウザ画面いっぱいに表示され、その中心に赤い車(この車でドライブします)が表示されます。

キー操作は以下の3つのみです:
 矢印キーの「下」: スタート/ストップ
 矢印キーの「左」: 左旋回
 矢印キーの「右」: 右旋回


とりあえず「下」を押すと動き出します(もう一度押すと止まります)。初期状態では5時の方角を向いているので右下方向に向かって移動を始めます(実際には車の位置は変わらず、地図部分がスクロールしていきます)。矢印の「左」や「右」を押して、なるべくコース上を走るようにしてみましょう:
2019081703
(↑ 1990年にセナとプロストが接触した1コーナー)


ぶっちゃけコースアウトしようが、何かと接触しようが車は動き続けます。なので「細かいことは忘れて」コースを走り続けましょう:
2019081704
(↑ 1989年にセナとプロストが接触したトライアングルシケイン、ここはこの赤い車でも難しい)


起動時に URL パラメータを与えることで初期位置と初期角度を変えることもできます:
 lat: 緯度
 lng: 経度
 anglelevel: 角度(何時の方向、という時計の短針の方角を示す。0~11 の整数)

下図は
 https://dotnsf.github.io/openmap_drive/?lat=43.733009&lng=7.4228981&anglelevel=4
にアクセスした時の様子です。画面下に有名なレストラン "La Rascasse(ラスカス)" が見えていますが、ここは F-1 モナコグランプリ市街地コース上です。これから最終コーナーに向かうラスカス・コーナーのあたり:
2019081705


地図で表示するのは必ずしもサーキットである必要はありません。こちら
 https://dotnsf.github.io/openmap_drive/?lat=35.6828558&lng=139.7596134&anglelevel=1
は日本の皇居前、内堀通りを走る状態からスタートします:
2019081706


実は以前に同様のゲームを Google MAPs API で作って教育目的に使っていたことがありました。他の地図 API と比較して多くの機能を持ち、今でも便利に使えると思ってはいるのですが、Google MAPs API は当時と異なり現在では API キーの取得が必要になってしまい、オープンな教材としては使いにくくなってしまったのでした。


という背景もあって、今回は Google MAPs API の API キーを使うのではなく、地図 API としてはOpenStreetMap API を、leaflet.js ライブラリを併用して使う形で作り直しました。加えて車の画像も「いらすとや」で公開されているものを直接参照し、CSS の transform で角度を変えて表示するように改良しました(この辺り、詳しくは index.html の内容を直接参照してください)。結果として(画像ファイルは不要になり)index.html ファイル1つだけで完結できるようになって、GitHub Pages で公開できる形にもなった、という副産物的なメリットも生まれました。


今回公開したファイルはあくまでテンプレートというか、「これを元に改良するための素」のつもりです。このゲームは上述のように3つのキーだけで(3種類の信号だけで)操作できるので、以前に紹介したキータッチと組み合わせて体感ゲームにしたり、IoT 的な要素を使ってデバイスからの信号を受け取れるようにしたり、身近なものをリモートコントローラー代わりにして使えたら面白いかな、と思っています。あと少し技術方向性は異なるけど、複数台の車を同時に走らせたりとかも面白そう。


このページのトップヘ