JavaScript Google Maps API 〜Map表示の(実装)方法〜

イントロダクション

前回はGoogleMapのAPIを使用する準備を行いました。
早い話が、APIのキーを取得しました。
取得した後に、ちょいと順序が違ってきてしまったので改めて、実装について触れようと思った次第です。

Google Maps JavaScript API

Googleから提供されているAPIドキュメントを見てみると、実装のサンプルがそのまま乗っています。
なので今まで深く触れていませんでした、が!どんな処理なのか今一度見てみようと思います。
上記のリンクより、こちらのリンクはJSFidleというものでHTML, CSS, JSが見れる優れものでした。

そして、上記のリンク先のコード配下になります。(コピペ)

      var map;
function initMap() {
    // Mapの生成処理(HTMLのDIVタグのid="map")
    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });
}

コードの内容

DIVタグにMapを埋め込みます。そのために使用するコードは下の部分です。

new google.maps.Map(DOMエレメント)

この処理で、DOMエレメント=DIVタグにマップを埋め込みます。(作成します)
そして、第二引数のJSONデータの部分について、これは見ればわかる人はわかるでしょう。(自分はこのようなのを見て理解するのに時間がかかったクチです(笑))

{ center: {lat: -34.397, lng: 150.644}, zoom: 8}

これをつなげると、上のようなコードになります。ちなみに開業しているのでぱっと見が違います。(見やすい)

map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });

このコードで、マップの作成ができたら次は。。。

Marker追加

マーカーの追加をやりたいと思うのが人情。。。(自分だではないと思います。)
そして、マーカーの追加は下のようにやるようです。上記のリンクよりコピペです。

// Initialize and add the map
function initMap() {
  // The location of Uluru
  var uluru = {lat: -25.344, lng: 131.036};
  // The map, centered at Uluru
  var map = new google.maps.Map(
      document.getElementById('map'), {zoom: 4, center: uluru});
  // The marker, positioned at Uluru
  var marker = new google.maps.Marker({position: uluru, map: map});
}

// The marker, positioned at Uluruの部分から下がマーカー追加処理になります。
1行で終わるのでとてもわかりやすいと思います。Map作成時と同じような形なのでここの説明は割愛します。

InfoWindow追加

そして、マーカーの次は情報ウィンドウが表示したい。。。
これもリンク先にサンプルコードからしてあります。
同様にコピペしました。

// This example displays a marker at the center of Australia.
// When the user clicks the marker, an info window opens.

function initMap() {
  var uluru = {lat: -25.363, lng: 131.044};
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: uluru
  });

  var contentString = '<div id="content" >'+
      '<div id="siteNotice"  >'+
      '</div >'+
      '<h1 id="firstHeading" class="firstHeading"    >Uluru</h1    >'+
      '<div id="bodyContent">'+
      '<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large ' +
      'sandstone rock formation in the southern part of the '+
      'Northern Territory, central Australia. It lies 335 km (208 mi) '+
      'south west of the nearest large town, Alice Springs; 450 km '+
      '(280 mi) by road. Kata Tjuta and Uluru are the two major '+
      'features of the Uluru - Kata Tjuta National Park. Uluru is '+
      'sacred to the Pitjantjatjara and Yankunytjatjara, the '+
      'Aboriginal people of the area. It has many springs, waterholes, '+
      'rock caves and ancient paintings. Uluru is listed as a World '+
      'Heritage Site.</p>'+
      '<p>Attribution: Uluru, <a href="https://en.wikipedia.org/w/index.php?title=Uluru&oldid=297882194">'+
      'https://en.wikipedia.org/w/index.php?title=Uluru</a> '+
      '(last visited June 22, 2009).</p>'+
      '</div>'+
      '</div>';

  var infowindow = new google.maps.InfoWindow({
    content: contentString
  });

  var marker = new google.maps.Marker({
    position: uluru,
    map: map,
    title: 'Uluru (Ayers Rock)'
  });
  marker.addListener('click', function() {
    infowindow.open(map, marker);
  });
}

このコードは以下の手順で処理を行っています。

  1. ウルル(地球のへそ)の位置(座標)をJSONで作成
  2. マップを作成
  3. HTMLコンテンツを作成
  4. 情報ウィンドウの生成
  5. マーカーの作成と情報ウィンドウの追加

こんな処理を行っています。
表示結果はリンク先にありますのでそちらを確認していただきたく思います。ぱっと見だけであれば、下にキャプチャを貼っておきます。

この画面はこちらに本物のサンプルがあります。

こんな感じです。

でわでわ。。。



JavaScriptでユーザー認証 〜シンプルな認証処理〜

イントロダクション

最近作成している、GoogleMapを使用したページがある程度見れるものになってきたので、そろそろと公開できるような形にしたいと思い、ちょいとギミックを追加します。

パスワード認証

皆さんご存知「パスワード認証」を実装します。
これを実装すれば、「<入力>」「<送信>」などのボタン押下で、不特定多数の人に地図データを登録される心配がなくなります。

パスワード認証の実装

シンプルにボタンをクリックしたらパスワード入力ダイアログボックスが表示され、入力→認証という流れで処理を行います。
パスワードは見つけられないように、サーバーサイド(PHP)で持つことにします。つまり実装としては下のような感じになります。

認証準備

まずは、入力とデータの送信が出来ないようにボタンを非表示にします。
これはシンプルにHTMLでstyle="display: none"を設定してやります。具体的には以下のようなHTMLコードに変更します。
<Before>

        <button class="butt1" onclick="sideWinHandle(sideWin)"><入力>   </button>
        <button class="butt2" onclick="postData()"><送信>  </button>

<After>

        <button name="loggedIn" class="butt1" onclick="sideWinHandle(sideWin)" style="display: none;"><入力></button>
        <button name="loggedIn" class="butt2" onclick="postData()" style="display: none;"><送信></button>
        <button onclick="openLoginForm()"><Login> </button>

そして、ボタン押下時に走らせる処理onclick="openLoginForm()"を設定します。
これが出来たら、あとはJSの実装のみです。

ズバリ下のような実装を追加します。ちょっと特殊なのはprompt()です。

function openLoginForm() {
var input = prompt("Login Form");
    if ('パスワード' === input) {
        var loggedInButton = document.getElementsByName("loggedIn");
        loggedInButton.forEach(but => {
            but.style = "display: visible";
        });
    }
}

これで下のように動きます。

  1. 「Login」ボタンを押下
  2. プロンプトが開き、入力を求める
  3. 入力した値がJSのinput変数に代入される(上のコード参照)

シンプルに実装できていると思います。

問題が1つ

この実装だと、パスワードがバレバレで、セキュリティ的にアウトです。しかし、今回の実装はあくまでサンプルなのでまぁよしとします。

実際の使用方法

実際は入力して判定するときにクライアント側ではなく、サーバー側(PHPなど)で判定を行います。
今の自分の実装だと、入力した値をサーバーに送信(Ajax通信)して判定結果をもとに画面の表示・非表示を切り替えるなどを行うのが、安全なやり方だと思います。

ぢつは。。。

今の実装をしていて気がつきました。「ハナっからこーすればいいよな?」と思っております。初めの初期表示時に処理を行うことに執着していて気がつかなかった次第です。



PHP Image File 〜iPhoneやAndroidでの画像送受信の問題〜

イントロダクション

GoogleMapを使用して見つけた場所(店など)をGoogleMapに登録するブラウザアプリケーションを作成中です。
途中まで作成していて携帯からアップロードした写真のデータが表示できない事象に遭遇しました。

スマホの写真(拡張子)

iPhoneではHEICを使用していました。Androidも同じものを使用している記事を見かけましたが、確認はしていません。
とりあえずのところは、画像を編集するのに提供されているコンバーターを使用する必要があり、既存のプログラムにも手を入れる必要があるということがわかりました。

既存プログラム

作成したプログラムのことですが、Ajax+PHPでの実装を行なっており、詳細に関してはこちらに記載しております。

問題

問題になっていることは、画像を送受信して表示できるものとできないものがあるということです。送受信するのはbase64でのデータをサーバーから送信しクライアントサイドでそれを表示しています。がスマホからサーバーに送信、DBに(BLOBで)登録したものは画面に表示できない事象にあってしまいました。テクノロジー的にも上記のようなファイルコンバートが必要になるようです。

結局

無理をして画像を表示する必要もないと判断しました。
ブラウザーからの入力はテキストのみにして、Youtubeの動画を表示するようにしました。
画面より、Youtubeの画像IDを入力しGoogleMapのinfoWindowに表示する方法をとりました。
とりあえずは、問題もなく動いているのでこの方法でサイトの方を作成していく予定です。

でわでわ。。。

関連ページ

  1. JS GoogleMaps API 〜オリジナル・データマップを作ろう〜
  2. 吹き出しにYoubetubeを埋め込む
  3. Ajax + XmlHttpRequest〜画像送信からDB登録して表示〜
  4. JS XmlHttpRequest 〜JSでの同期/非同期通信〜
  5. JS Google Maps API 〜GeoLocation 現在位置の取得〜
  6. AngularJS + PHP 〜AngularJSの実装〜
  7. AngularJS + PHP 〜AngularJSの実装2〜



Google Maps API 〜吹き出しにYoutubeを埋め込む〜

``### イントロダクション
ようやく、休みになったのでJSでのGoogle Mapをやります。前は、画像ファイルをアップロードして。。。と考えていましたが、動画の方が良いと判断しました。Thetaも買ったので(笑)

Google Maps + Youtube

色々考えた結果こうなりました、そして早速実装したものの、動画表示できない事件が。。。

ちなみにスマホでは灰色の部分も表示されませんでした。。。

Youtube Player API

調べて見たところ、上のYoutube Player APIで吹き出し部分にYoutubeが埋め込めるようなのです。

余談ですが、こんな方法もいけるようです。が、自分の場合はダメでした。。。
とりあえずはコードを写経して見ます。

しかし、さして変化もなく。。。

やっぱりこれか?

Refused to display 'https://www.youtube.com/watch?v=MwI4m_LLugo&feature=youtu.be' in a frame because it set 'X-Frame-Options' to 'sameorigin'.

このHTMLコードがコンポン的な原因のようです、早い話がYoutubeにアクセスできない状態のため上のHTMLも表示できない。。。という仮説です。
まとめると「iframeでアクセスできるようにすればOK!」というわけです。

戦いの結果

敵将の首を討ち取りました!
原因はiframeに渡しているURLが不適切なツェツなので表示されないということでした。
表示できない時のURL
https://www.youtube.com/watch?v=t-6PiKxDX2E
表示できたURL
https://www.youtube.com/embed/t-6PiKxDX2E
watchembedで違いがあり、iframeに埋め込むのは「embed」の方を使用するべきだったということでした。
でわでわ。。。



Google VR View 〜360°の写真とビデオをHTMLに埋め込む〜

イントロダクション

360度を写せるカメラが簡単に手に入る世の中になってきました。筆者はリコーの360度カメラを持っています。なかなか使い勝手の良いものです。

さて、現在作成中のGoogleMapを使用したブラウザアプリに写真を埋め込むような形で実装しようと考えていましたが、PHPでの実装ではXmlHttpRequestでの通信処理が遅いのと、不具合(写真が時々表示できない)があるのと、深く追求うする気もないのでやめることにしました。

360度カメラで撮影したものです。

その代替え案として

次のようなものがあることを知りました。Google VR Viewです。

Google VR View

これ使って動画や、写真をHTMLに埋め込もうと考えたので、調査をすることにしました。

概要

HTMLに360度画像を埋め込むことができます。そのために使用するのが次のJSファイルです。

  • vrview.min.js

HTML内の配置するタグには下記のDIVタグをセットします。

<div id='vrview'></div>

手順

  1. vrview.min.jsを読み込む
  2. idを指定した表示領域を作成
  3. JSでnew VRView.Playerをインスタンス化

サンプル

ここのページに「こんな感じ」というものがありました。

埋め込む方法

JSを使用して埋め込む方法がありました。使用するJSファイルは「vrview.min.js」のようです。

<script> src="https://storage.googleapis.com/vrview/2.0/build/vrview.min.js"></script>

そして、360度のイメージファイルは圧縮率などを考慮に入れると「JPEG」がオススメのようです。
圧縮を改善するためにjpegを使用することをお勧めします。

メディアの配置

上のようにJSでファイルを読み込むような形でHTMLに埋め込むのでJPEGなどのファイルを適当な場所に配置する必要があります。
そして、既存の問題もあるようです。PHPでの画像表示がうまくいかない原因もここにありそうです。

Web上の既知の問題
(JavaScript APIを使用せずに)iframeを明示的に宣言し、コードと画像が異なるサーバでホストされている場合、iOS Safariでは360度画像の方向が正しくありません。

メディアとVR Viewコードが異なるサーバーでホストされている場合、360°ビデオはOSX Safariでは機能しません。

2のべき乗でない正方形の画像は、ChromeおよびSafari iOS 8では正しく表示されない場合があります。

配置するタグ

<div id='vrview'></div>

VRView.Playerのインスタンス化

ロードイベント(onload)で起動するように設定します。
言葉を変えると、オンロードイベントに下の「onVrViewLoad」を登録してVRView.Playerをインスタンス化する関数を実行するというわけです。

// onVrViewLoadをオンロードイベントで動くように登録しています。
window.addEventListener('load', onVrViewLoad);

// onVrViewLoadを定義しています。
function onVrViewLoad() {
  // Selector '#vrview' finds element with id 'vrview'.
  var vrView = new VRView.Player('#vrview', {
    video: '/url/to/video.mp4',
    is_stereo: true
  });
}

まとめ

意図しないところで、PHP画像アップロード問題の原因がわかったものの解決に至らずですが、とりあえずはWebアプリに関して

  1. 画像でなくURLを渡すような形で表示する
  2. URL形式でHTMLに出力してJSでコントロールする

このような形で実装すると良いという発見がありました。
そして、360°の写真とビデオはこれも URLで参照先(画像などの配置場所)を指定する形でHTMLに出力するので問題なくいけそうだということがわかりました。

でわでわ。。。