サンプル・プログラムの実行例
サンプル・プログラムのダウンロード
gmapSolarSystem.html | サンプル・プログラム本体。 |
準備
0020: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
0021: <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB-LE2H8D9At3-J7aqwuQW2oJ-_ulXcozA®ion=JP&libraries=geometry"></script>
まず、GoogleマップAPIを利用するにはキーが必要となる。
「Google Maps APIs for Web」にアクセスし、「キーを取得」ボタンをクリックすると無料で取得できる。これを "https://maps.googleapis.com/maps/api/js?key=" に続く部分に記入すること。ダウンロードしたコンテンツに書かれているキーは、当サイトでしか利用できない。また、Google Cloud Console に入り、GoogleMaps JavaScript API、Google Maps Geocoding API を有効にする。
なお、後述するとおり geometryライブラリを利用するので、URLのオプションに libraries=geometry を加えてある。
0023: //Googleマップ用パラメータ
0024: var gmap;
0025: var gmapid = 'gmap'; //マップID
0026: var gwidth = 600; //地図幅
0027: var gheight = 400; //地図高
0028: var msize = 32; //惑星マーカーのサイズ
0029:
0030: //初期値
0031: var lat_center = 35.681111; //地図の中心点(緯度)=東京駅
0032: var lng_center = 139.766667; // (経度)
0033: var lat_sun = 35.681111; //太陽の位置(緯度)=東京駅
0034: var lng_sun = 139.766667; // (経度)
0035: var lat_earth = 35.466111; //地球の位置(緯度)=横浜駅
0036: var lng_earth = 139.6225; // (経度)
0037: var zoom = 7; //ズームの初期値
0038: var maptype = 'roadmap'; //マップタイプ
なお、惑星マーカーのサイズ msize は、後述する太陽のアイコン、惑星の基本情報に指定するものと同じであること。
0044: //太陽のアイコン
0045: const sun = {
0046: icon: 'https://iconhoihoi.oops.jp/sozai/icon/166-planet/icon_1r_32.png'
0047: }
0048: //惑星の基本情報
0049: // radius:軌道半長径(AU),icon:アイコンファイル,
0050: // color:軌道描画色,weight:軌道の太さ,
0051: // heading:アイコン配置位置(真北から時計回りの角度)
0052: let planets = {
0053: mercury: {
0054: radius: 0.3871,
0055: icon: 'https://iconhoihoi.oops.jp/sozai/icon/166-planet/icon_2y_32.png',
0056: color: '#FF0000',
0057: weight: 1,
0058: heading: 45
0059: },
0060: venus: {
0061: radius: 0.7233,
0062: icon: 'https://iconhoihoi.oops.jp/sozai/icon/166-planet/icon_3g_32.png',
0063: color: '#FF0000',
0064: weight: 1,
0065: heading: 90
0066: },
惑星の情報は、コメントにあるように、radius:軌道半長径(AU),icon:アイコンファイル,color:軌道描画色,weight:軌道の太さ,heading:アイコン配置位置(真北から時計回りの角度)から成る。
円軌道でよければ、変数 planets に情報を追加することで、いくつでも描くことができる。
解説:Googleマップとイベントの準備
0280: /**
0281: * Googleマップ関係
0282: */
0283: google.maps.event.addDomListener(window, 'load', function() {
0284: var mapdiv = document.getElementById(gmapid);
0285: var myOptions = {
0286: zoom: zoom,
0287: center: new google.maps.LatLng(lat_center, lng_center),
0288: mapTypeId: google.maps.MapTypeId.maptype,
0289: mapTypeControl: true,
0290: scaleControl: true
0291: };
0292: gmap = new google.maps.Map(mapdiv, myOptions);
0293:
0294: //初期化
0295: initialize();
0296:
0297: //event.addListener
0298: google.maps.event.addListener(gmap, 'click', function(e) {
0299: onClickMap(e.latLng);
0300: });
0301: });
解説:初期化処理
0231: /**
0232: * 初期化処理
0233: * @paramなし
0234: * @returnなし
0235: */
0236: function initialize() {
0237: //太陽の位置、マーカー
0238: l_sun = new google.maps.LatLng(lat_sun, lng_sun);
0239: //描画済みのマーカーがあれば消去
0240: if (markers['sun'] != null) {
0241: markers['sun'].setMap(null);
0242: }
0243: //マーカーを描く
0244: markers['sun'] = new google.maps.Marker({
0245: position: l_sun,
0246: icon: new google.maps.MarkerImage(
0247: sun.icon,
0248: new google.maps.Size(msize, msize),
0249: new google.maps.Point(0, 0),
0250: new google.maps.Point(msize / 2, msize / 2), //位置調整
0251: ),
0252: map: gmap
0253: });
0254:
0255: //地球の位置、マーカー
0256: l_earth = new google.maps.LatLng(lat_earth, lng_earth);
0257: //描画済みのマーカーがあれば消去
0258: if (markers['earth'] != null) {
0259: markers['earth'].setMap(null);
0260: }
0261: //マーカーを描く
0262: markers['earth'] = new google.maps.Marker({
0263: position: l_earth,
0264: icon: new google.maps.MarkerImage(
0265: planets['earth'].icon,
0266: new google.maps.Size(msize, msize),
0267: new google.maps.Point(0, 0),
0268: new google.maps.Point(msize / 2, msize / 2), //位置調整
0269: ),
0270: map: gmap
0271: });
0272:
0273: //距離計算
0274: var distance = google.maps.geometry.spherical.computeDistanceBetween(markers['sun'].position, markers['earth'].position);
0275:
0276: //太陽系を描く
0277: drawSolarSystem(markers['sun'].position, distance);
0278: }
まず、太陽の位置(緯度・経度)を取り出し、マーカーとして表示する。このとき、あとでマーカーを移動するために、マーカーはオブジェクト変数 markers に代入しておく。
地球についても同様に処理する。
次に、惑星軌道を描く基準となる、太陽=地球間の距離を求める。
GoogleマップAPIの geometryライブラリには2点間の距離計算メソッド spherical.computeDistanceBetween が用意されているので、これを利用することにする。
これらが揃ったら、太陽系を描画するユーザー関数 drawSolarSystem を呼び出す。
解説:各惑星の軌道を描き、マーカーを設置する
0121: /**
0122: * 惑星の軌道を描く
0123: * @param object latlng 太陽の位置(緯度・経度)
0124: * @param double distance太陽=地球距離(メートル)
0125: * @returnなし
0126: */
0127: function drawSolarSystem(latlng, distance) {
0128: //惑星の数だけ繰り返す
0129: for (let key in planets) {
0130: radius = distance * planets[key].radius; //軌道半長径
0131: //描画済みの円があれば消去
0132: if (orbits[key] != null) {
0133: orbits[key].setMap(null);
0134: }
0135: //円を描く
0136: orbits[key] = new google.maps.Circle({
0137: map: gmap,
0138: clickable: false,
0139: center: latlng, //中心点
0140: radius: radius, //半径(メートル)
0141: fillOpacity: 0.0, //塗りつぶし透過度
0142: strokeColor: planets[key].color, //外周色
0143: strokeWeight: planets[key].weight //外周太さ(ピクセル)
0144: });
0145:
0146: //惑星マーカーを設置
0147: if (key != 'earth') {
0148: p_latlng = google.maps.geometry.spherical.computeOffset(latlng, radius, planets[key].heading);
0149: //描画済みのマーカーがあれば消去
0150: if (markers[key] != null) {
0151: markers[key].setMap(null);
0152: }
0153: //マーカーを描く
0154: markers[key] = new google.maps.Marker({
0155: position: p_latlng,
0156: icon: new google.maps.MarkerImage(
0157: planets[key].icon,
0158: new google.maps.Size(msize, msize),
0159: new google.maps.Point(0, 0),
0160: new google.maps.Point(msize / 2, msize / 2), //位置調整
0161: ),
0162: map: gmap
0163: });
0164: }
0165: }
0166: }
GoogleマップAPIには円を描画するメソッド Circle が用意されている。
惑星の軌道は、正確には楕円であるが、今回はメソッド Circle を利用することでプログラムを簡素化した。軌道がかなり楕円になっている冥王星は、今回は除外した。
あとで軌道を移動するために、メソッド Circle で描いたオブジェクト情報はオブジェクト変数 orbits に格納しておく。
ユーザー関数 initialize と同様に、各惑星のマーカーを軌道上に設置してゆく。
設置場所(緯度・経度)は、太陽の位置から planets[].heading で指定する方向に、軌道半長径だけ離れた位置に設置することにする。GoogleマップAPIの geometryライブラリに用意されているメソッド spherical.computeOffset を利用することで、その位置を求めている。
なお、太陽や地球と同様、あとで軌道を移動するために、マーカーはオブジェクト変数 markers に代入しておく。
解説:各惑星の軌道、マーカーを消去する
0168: /**
0169: * 各惑星の軌道、マーカーを消去する
0170: * @paramなし
0171: * @returnなし
0172: */
0173: function clearSolarSystem() {
0174: for (let key in planets) {
0175: //描画済みのマーカーがあり、地球以外なら消去
0176: if ((markers[key] != null) && (key != 'earth')) {
0177: markers[key].setMap(null);
0178: }
0179: //描画済みの円があれば消去
0180: if (orbits[key] != null) {
0181: orbits[key].setMap(null);
0182: }
0183: }
0184: };
描画時に代入したオブジェクト変数 orbits および markers を参照しながら、GoogleマップAPIメソッド setMap で消去していく。
解説:地図クリック時の処理
0186: /**
0187: * 地図クリック時の処理
0188: * @param object lat_lngクリックされた座標
0189: * @returnなし
0190: */
0191: function onClickMap(lat_lng) {
0192: //太陽と地球のどちらが選ばれているか
0193: var radios = document.myform.selector;
0194: for (var i = 0; i < radios.length; i++) {
0195: if (radios[i].checked) {
0196: selector = radios[i].value;
0197: break;
0198: }
0199: }
0200: var longitude = 'lng_' + selector;
0201: var latitude = 'lat_' + selector;
0202: if (selector == 'sun') {
0203: icon = sun.icon;
0204: } else {
0205: icon = planets['earth'].icon;
0206: }
0207:
0208: //描画済みのマーカーがあれば消去
0209: if (markers[selector] != null) {
0210: markers[selector].setMap(null);
0211: }
0212: //マーカーを描く
0213: markers[selector] = new google.maps.Marker({
0214: position: lat_lng,
0215: icon: new google.maps.MarkerImage(
0216: icon,
0217: new google.maps.Size(msize, msize),
0218: new google.maps.Point(0, 0),
0219: new google.maps.Point(msize / 2, msize / 2), //位置調整
0220: ),
0221: map: gmap
0222: });
0223:
0224: //距離計算
0225: var distance = google.maps.geometry.spherical.computeDistanceBetween(markers['sun'].position, markers['earth'].position);
0226:
0227: //太陽系を描く
0228: drawSolarSystem(markers['sun'].position, distance);
0229: }
違う点は、冒頭で、太陽と地球のどちらのラジオボタンが選ばれているかを調べ、それによって、クリックされた座標を太陽に割り当てるか、地球に割り当てるかを場合分けしているところである。
学生時代、この太陽系の広さを実感してもらうために、東京駅に太陽が、横浜駅に地球があったとしたら、太陽系はどこまで広がっているか、日本地図の上にマッピングし、各地を撮影した8ミリ映画を作ったことがある。
今回は、同じことをGoogleマップとJavaScriptで実装してみることにする。