知識の枝

"All is well"

VueでGoogleMapを埋め込む(APIキー不要)

約75日前 2022年3月3日21:42
デジタル
HTML JavaScript API Vue.js

改訂履歴


2022/3/3 投稿

1. GoogleMapを埋め込む


タイトルの通りGoogleMapを埋め込みます。

”検索フォームに地名を入力するとその地域の地図が表示される”

そんな機能を作りたいと思います。

完成イメージ



使うのは

  • Maps Embed API
  • Vue.js
です。
※Vue3、.vueコンポーネント、Composition APIを使用します


2. Maps Embed API


はてさて、Maps Embed API とはなんぞやという話ですが、、、

Googleが提供しているGoogle Mapをウェブページに埋め込む機能の1種です。

HTMLの<iframe>を使用することで利用可能です。

書き方は下記の通りです。
<iframe
src="https://maps.google.co.jp/maps?output=embed&q=検索ワード"
width="800"
height="450"
style="border: 0"
allowfullscreen=""
loading="lazy"
>
</iframe>
"検索ワード"の部分に地名や緯度・経度を入力すると、その地域の地図が表示されます。

ここでベースとなっているのが下記URLです。

"https://maps.google.co.jp/maps?output=embed&q="

このURLをiframeタグのsrc属性にわたすことで、GoogleMapの埋め込みが行われます。


"検索ワード"をフォームで入力して、リアクティブに地図を書き換えるのが今回のゴールです。


3. Vueでリアクティブ化


ではどのようにしてリアクティブに "検索ワード" 部分を書き換えましょうか?

今回はVue.jsを使用して解決してみようと思います。


機能を分解して考えてみましょう。

最終的に欲しいのは
"入力した地名or緯度経度の地図を表示する" という機能です。

ですので必要なのは、、、

  • 文字列を入力する機能
  • 入力された文字列をURLの後ろにくっつける機能
  • くっつけたURLをiframeのsrc属性にわたす機能
  • 地図を表示する機能

の4つとなります。

ちなみに4つ目の "地図を表示する機能" はMaps Embed APIがやってくれるので、1~3つ目をVue.jsで実装します。


3.1 - 入力


"文字列を入力する機能" は通常のinputタグを利用します。

.vueコンポーネントファイル「GoogleMapSearch.vue」を作成します。
GoogleMapSearch.vue
<template>
<div>
<input v-model="searchWord">
<google-map v-if="searchWord != ''" :place="searchWord"></google-map>
</div>
</template>

<script>
import GoogleMap from './GoogleMap.vue'
import {ref} from 'vue'

export default {
components: {
GoogleMap,
},
name: 'GoogleMapSearch',
setup() {
const searchWord = ref('')
return {
searchWord,
}
}
}
</script>
<google-map>というコンポーネントはGoogleMapを表示するコンポーネントで、文字列を受け取って地図を表示する部品です。
これは後から作ります。


ここでは、
<input>タグで文字列の入力を受け付け、入力された文字列を変数 "searchWord" に格納しています。
<input v-model="searchWord">


格納された文字列は<google-map>コンポーネントに"place"という変数に入ってわたされます。
:place="searchWord"


また、文字列が未入力の場合は<google-map>コンポーネントを表示しないようにしています。
v-if="searchWord != ''"


入力部分が完成しましたので、次は受け取る側のコンポーネントファイル「GoogleMap.vue」を作成します。


3.2 - 受け取って加工


地図を表示する部品を作成します。

この部品の役割は、親のコンポーネント(今回の場合はGoogleMapSearch.vue)から受け取った文字列を加工して、iframeのsrc属性にわたすことです。

部品となる.vueコンポーネントファイル「GoogleMap.vue」を作ります。
GoogleMap.vue
<template>
<div>
<iframe
:src="src"
width="800"
height="450"
style="border: 0"
allowfullscreen=""
loading="lazy"
>
</iframe>
</div>
</template>

<script>
import { ref, computed } from "vue";

export default {
name: "GoogleMap",
props: {
place: [String],
},
setup(props) {
const src = computed(
() => "https://maps.google.co.jp/maps?output=embed&q=" + props.place
);
return {
src,
};
},
};
</script>
<script>の部分で親コンポーネントから「文字列」を受け取り、加工しています。

まずは受け取る部分。
props: {
place: [String],
}
propsでplace(=文字列)を受け取り、コンポーネント内で使えるようにします。


受け取った"place"をMaps Embed APIのURLの後ろにくっつけます。
const src = computed(
() => "https://maps.google.co.jp/maps?output=embed&q=" + props.place
)
算出プロパティのcomputedを使い、変数srcに加工後のURLが格納されるようにしています。

propsで受け取ったデータは "props.変数名" で取り出せます。
したがって親コンポーネントから受け取った文字列は props.place で取り出せます。

取り出したprops.placeをURLの後ろにくっつけて完成です。
"https://maps.google.co.jp/maps?output=embed&q=" + props.place



3.3 - iframeにわたす


先程加工したURLデータは変数srcに入っていますので、このsrcをiframeのsrc属性に割り当てます。
<iframe
:src="src"
width="800"
height="450"
style="border: 0"
allowfullscreen=""
loading="lazy"
>
</iframe>
v-bindを使いsrc属性に変数srcを割り当てました。
:src="src"


これてすべてが繋がりました。

文字を入力するとその地域の地図が表示されます。


4. 弱点もある


今回紹介した方法には弱点があります。

それは、読み込んだGoogleMapの中の情報をJavascriptで取得できない点です。

iframeで読み込まれたMap内の情報はChromeブラウザの"検証"で要素を見ることができます。


見ることはできますが、これらの要素から情報を取り出すことは同一オリジンポリシーに引っ掛かる為できません。

"情報を取り出す"というのは例えば getElementbyId("○○") でタグを指定して、中の文字列を取り出したりする行為です。

iframe内の情報を取り出す手段自体はありますが、残念ながらGoogleMapのiframeはオリジンが異なるため取り出せません。

調べてみると別の方法なら可能みたいなので、継続して調査してみようと思います。
nguyen 約73日前 2022年3月5日14:29 返信する
こんにちは
DjangoでChatworkAPI関連で
チャット送信やチャット取得など
サンブルソースがありませんか
よろしくお願いいたします。
chuna 約72日前 2022年3月6日17:05
nguyenさん
コメントありがとうございます。
ChatWorkAPIは初耳だったので調べてみました。
使い方をまとめて記事にしますので、今しばらくお待ち下さい。

また質問があればそちらの記事へお願いいたします。
chuna 約72日前 2022年3月6日21:52
解説記事を書きましたのでこちらからどうぞ。
https://chuna.tech/detail/101/
nguyen 約70日前 2022年3月8日20:51 返信する
どうもありがとうございました。
参考させていただきます。

どうぞよろしくお願いいたします。