var VtmBusStopMap = function(options) { var self = this; self.markers = []; self.map = null; self.listeners = { departureSelected: [], arrivalSelected: [], }; self.ajaxObj = null; // デフォルト値をマージ self.options = VtmUtil.mergeObject({ id: null, key: VTM_EKISPERT_KEY, hidePlaceSet: false, enabledTreasure: false, activeCategory: '駅、バス停', activeType: undefined, categories: [ // categoryオブジェクトの必須項目は // code // name // englishName or englishNameHtml // iconClass { code: '駅、バス停', name: 'バス停', englishName: 'Bus Stop', iconClass: 'fas fa-bus-alt', }, { code: 'レストラン、喫茶', name: '飲食店', englishNameHtml: 'Restaurant
/ Cafe', iconClass: 'fas fa-utensils', }, { code: 'スーパー、コンビニ', name: '店舗', englishNameHtml: 'Supermarket /
Convenience Store', iconClass: 'fas fa-shopping-cart', }, { code: '薬局', name: '薬局', englishNameHtml: 'Drug
Store', iconClass: 'fas fa-pills', }, { code: '病院', name: '病院', englishName: 'Hospital', iconClass: 'fas fa-hospital', }, { code: '銀行、ATM', name: '銀行・ATM', englishNameHtml: 'Bank
/ ATM', iconClass: 'fas fa-yen-sign', }, { code: '公共施設', name: '公共施設', englishNameHtml: 'Public
Facility', iconClass: 'fas fa-university', }, { code: '観光スポット', name: '観光施設', englishNameHtml: 'Tourist
Spot', iconClass: 'fas fa-vihara', }, ], }, options); var template = ''; template += '
'; template += '
'; template += '
'; template += '
'; template += '
'; template += '
'; template += ' '; template += '
'; template += '
'; template += '
'; template += '
'; template += '
'; template += ' '; template += ' '; self.options.categories.forEach(function(category) { template += ' '; }); template += ' '; template += ' '; self.options.categories.forEach(function(category) { template += ' '; }); template += ' '; template += '
'; if (category.nameHtml || category.name) { template += '
'; } if (category.englishNameHtml || category.englishName) { template += '
'; } if (category.koreanNameHtml || category.koreanName) { template += '
'; } if (category.simplified_chineseNameHtml || category.simplified_chineseName) { template += '
'; } if (category.traditional_chineseNameHtml || category.traditional_chineseName) { template += '
'; } if (category.thaiNameHtml || category.thaiName) { template += '
'; } template += '
'; if (category.nameHtml || category.name) { template += ' ' + (category.nameHtml || category.name) + ''; } if (category.englishNameHtml || category.englishName) { template += ' ' + (category.englishNameHtml || category.englishName) + ''; } if (category.koreanNameHtml || category.koreanName) { template += ' ' + (category.koreanNameHtml || category.koreanName) + ''; } if (category.simplified_chineseNameHtml || category.simplified_chineseName) { template += ' ' + (category.simplified_chineseNameHtml || category.simplified_chineseName) + ''; } if (category.traditional_chineseNameHtml || category.traditional_chineseName) { template += ' ' + (category.traditional_chineseNameHtml || category.traditional_chineseName) + ''; } if (category.thaiNameHtml || category.thaiName) { template += ' ' + (category.thaiNameHtml || category.thaiName) + ''; } template += '
'; template += '
'; template += '
'; template += ' '; template += '
'; template += '
'; if (self.options.enabledTreasure) { template += ' '; } template += '
'; self.vm = new Vue({ el: '#' + self.options.id, template: template, data: { id: self.options.id, locating: false, // 現在地を取得中かどうか activeCategory: self.options.activeCategory, // 選択されているカテゴリ activeType: self.options.activeType, // 選択されているタイプ(あれば) iconCurrentLocation: VTM_LIB_URL + 'vtmBusStopMap/iconCurrentLocation.svg', showTextbox: true, }, mounted: function() { var elm = document.getElementById(self.options.id); var $elm = $(elm); $elm.data("self", self); var topLeftControls = $elm.find(".topLeftControls").get(0); var bottomRightControls = $elm.find(".bottomRightControls").get(0); // Google Maps初期化 var gmapOptions = { center: self.options.center || { lat: 36.70187372130401, lng: 137.21260814190376 }, // 富山駅 zoom: 14, fullscreenControl: false, mapTypeControl: false, scaleControl: true, streetViewControl: false, }; var gmapElm = $elm.find(".gmap").get(0); self.map = new google.maps.Map(gmapElm, gmapOptions); if (bottomRightControls) { self.map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(bottomRightControls); } if (!self.options.hidePlaceSet) { self.map.addListener("click", function(e) { console.log(e.latLng.lat(), e.latLng.lng()); var lat = e.latLng.lat(); var lng = e.latLng.lng(); var place = {name: "選択された地点", englishName: "Selected Place", koreanName: "선택된 장소", simplified_chineseName: "所选位置", traditional_chineseName: "所選位置", thaiName: "สถานที่ที่เลือก", code: null}; self.openInfoWindow("latlng", place, lat, lng); }); } self.infoWindow = new google.maps.InfoWindow({ zIndex: 9999 }); self.departureInfoWindow = new google.maps.InfoWindow({ zIndex: 9999 }); self.arrivalInfoWindow = new google.maps.InfoWindow({ zIndex: 9999 }); // 駅名入力パーツ#1初期化 var stationApp1Element = document.getElementById(self.options.id + '-stationApp'); var stationApp1 = new expGuiStation(stationApp1Element); stationApp1.setConfigure("apiURL", "https://api-toyama.vtfm.jp/"); stationApp1.setConfigure("agent", 1); stationApp1.setConfigure("key", VTM_EKISPERT_KEY); stationApp1.setConfigure("placeholder", "駅・バス停・施設名を入力"); stationApp1.setConfigure("gcs", "wgs84"); stationApp1.setConfigure("addGeoPoint", true); stationApp1.setStationSort([stationApp1.createSortObject("電車", "train"), stationApp1.createSortObject("バス", "bus"), stationApp1.createSortObject("施設", "landmark")]); // 駅名入力パーツで入力が確定されたとき呼ばれる stationApp1.bind("change", function () { var point = stationApp1.getPointObject(stationApp1.getStationCode()); var geoPoint = stationApp1.getStationGeoPoint(); var lat = parseFloat(geoPoint.lati_d); var lng = parseFloat(geoPoint.longi_d); self.map.setCenter({ lat: lat, lng: lng }); self.map.setZoom(17); var place = {}; if (point) { place = {name: point.name, englishName: point.name, code: point.code}; } else { place = {name: "選択された場所", englishName: "Selected Place", code: null}; } self.openInfoWindow("latlng", place, lat, lng); var url = "https://api-toyama.vtfm.jp/v1/place"; var params = { key: self.options.key, provider: VTM_PROVIDER, category: self.options.activeCategory, q: self.map.getCenter().lat() + ',' + self.map.getCenter().lng(), }; if (self.options.activeType !== undefined && self.options.activeType != "undefined") { params.type = self.options.activeType; } $.getJSON(url, params) .then(function(res) { if (!res || !res.resultSet || !res.resultSet.places) { console.error("レスポンス不正", res); return; } res.resultSet.places.forEach(function(place) { var a = place.location.split(","); if (a.length != 2) { return; } if (self.markers.some(function(m) { return m.title == place.name; })) { return; } var lat = parseFloat(a[0]); var lng = parseFloat(a[1]); var marker_options = { position: { lat: lat, lng: lng }, map: self.map, title: place.name, }; if (place.markerurl !== undefined && place.markerurl != "") { marker_options.icon = { url: VTM_LIB_URL.replace('/lib/','') + place.markerurl, scaledSize: new google.maps.Size(31, 49) }; } var marker = new google.maps.Marker(marker_options); marker.addListener("click", function() { self.openInfoWindow("facility", place, lat, lng, marker); }); self.markers.push(marker); }); }) .catch(function(err) { console.error(err); }); }); stationApp1.dispStation(); function setPlaceholder(languageCode) { var languageStrToLocale = { "ja": "japanese", "en": "english", "ko": "korean", "zh-cn": "simplified_chinese", "zh-tw": "traditional_chinese", "th": "thai", }; stationApp1.setConfigure("language", languageStrToLocale[languageCode]); stationApp1.setConfigure("apiParam", "language=" + languageCode + "&provider=" + encodeURIComponent(VTM_PROVIDER)); switch(languageCode) { case "ja": stationApp1.setConfigure("placeholder", "駅・バス停・施設名を入力"); break; case "en": stationApp1.setConfigure("placeholder", "Station / Bus stop / Facility name"); break; case "ko": stationApp1.setConfigure("placeholder", "역 / 버스 정류장 / 시설 명"); break; case "zh-cn": stationApp1.setConfigure("placeholder", "车站 / 巴士站 / 设施名称"); break; case "zh-tw": stationApp1.setConfigure("placeholder", "車站 / 巴士站 / 設施名稱"); break; case "th": stationApp1.setConfigure("placeholder", "สถานี / ป้ายรถเมล์ / ชื่อสถานที่"); break; } } VtmCommon.addEventListener("languageChanged", function(languageCode) { setPlaceholder(languageCode); }); setPlaceholder(localStorage.getItem("language") || "ja"); this.showMarkers(self.options.activeCategory, self.options.activeType); }, methods: { /** * 指定されたカテゴリがアクティブか判定する。 */ isActive: function(category, type) { if (type == 'undefined') { return category == this.activeCategory && this.activeType === undefined; } else { return category == this.activeCategory && type == this.activeType; } }, /** * マーカーのデータ読み込み(全件終わるまで繰り返す) */ loadMarkers: function(url, params, category, type, cursor) { var thisObj = this; if (cursor !== undefined) { params.cursor = cursor; } else if (self.ajaxObj != null) { // 別カテゴリーの差分読み込み中の場合は、その処理を停止する self.ajaxObj.abort(); } self.ajaxObj = $.ajax({ type: 'GET', url: url, data: params, dataType: 'json' }) .done(function(res) { if (!res || !res.resultSet || !res.resultSet.places) { console.error("レスポンス不正", res); return; } var new_cursor = res.resultSet.cursor; res.resultSet.places.forEach(function(place) { var a = place.location.split(","); if (a.length != 2) { return; } if (self.markers.some(function(m) { return m.title == place.name; })) { return; } var lat = parseFloat(a[0]); var lng = parseFloat(a[1]); var marker_options = { position: { lat: lat, lng: lng }, map: self.map, title: place.name, }; if (place.markerurl !== undefined && place.markerurl != "") { marker_options.icon = { url: VTM_LIB_URL.replace('/lib/','') + place.markerurl, scaledSize: new google.maps.Size(31, 49) }; } var marker = new google.maps.Marker(marker_options); marker.addListener("click", function() { self.openInfoWindow("facility", place, lat, lng, marker); }); self.markers.push(marker); }); self.vm.activeCategory = category; if (type !== undefined && type != "undefined") { self.vm.activeType = type; } else { self.vm.activeType = undefined; } if (res.resultSet.places.length > 0) { thisObj.loadMarkers(url, params, category, type, new_cursor); } }) .fail(function(err) { console.log(err); }); }, /** * 各カテゴリのアイコンをクリックしたとき呼ばれる。 */ showMarkers: function(category, type) { self.markers.forEach(function(marker) { marker.setMap(null); }); self.markers = []; var url = "https://api-toyama.vtfm.jp/v1/place"; var params = { key: self.options.key, provider: VTM_PROVIDER, category: category, }; if (type !== undefined && type != "undefined") { params.type = type; } this.loadMarkers(url, params, category, type, undefined); }, /** * Map右下の現在地を取得アイコンをクリックしたとき呼ばれる。 */ getCurrentLocation: function() { self.vm.locating = true; function _getCurrentLocation(onSuccess, onFailure) { if (!navigator.geolocation) { onFailure("この端末では位置情報が取得できません"); return; } navigator.geolocation.getCurrentPosition( // 取得成功した場合 function(position) { onSuccess(position); }, // 取得失敗した場合 function(error) { var msg; switch(error.code) { case 1: // PERMISSION_DENIED if (location.href.indexOf("http://") >= 0) { msg = "位置情報の利用が許可されていません。\nお使いのブラウザでは、http://のページにおいて位置情報を利用できない可能性があります。"; } else { msg = "位置情報の利用が許可されていません"; } break; case 2: // POSITION_UNAVAILABLE msg = "現在位置が取得できませんでした"; break; case 3: // TIMEOUT msg = "タイムアウトになりました"; break; default: msg = "現在位置が取得できませんでした(エラーコード: " + error.code + ")"; break; } onFailure(msg); } ); }; _getCurrentLocation(function(position) { self.map.setCenter({ lat: position.coords.latitude, lng: position.coords.longitude }); var place = {name: "現在地", englishName: "Selected Current Location", code: null}; self.openInfoWindow("latlng", place, position.coords.latitude, position.coords.longitude, null); self.vm.locating = false; }, function(err) { self.vm.locating = false; alert(err); }); }, }, }); }; VtmBusStopMap.prototype = { /** * イベントリスナー追加 */ addEventListener: function(eventName, func) { var self = this; if (!self.listeners[eventName]) { console.error("イベント名 [" + eventName + "] はサポートされていません"); return; } self.listeners[eventName].push(func); }, /** * ポップアップを開く。 * place: * 必須 {:name, :englishName, :code} * オプショナル {:category, :url, :comment, :address, :imageurl} * marker, hidePlaceSetはオプショナル。 */ openInfoWindow: function(type, place, lat, lng, marker, hidePlaceSet) { var self = this; // Google Mapsの中はc-lang-*が効かなかったような気がするので、この方法で言語を切り替える var language = localStorage.getItem("language") || "ja"; switch(language) { case "en": var labelDeparture = "Set as From"; var labelArrival = "Set as To"; var labelTreasure = "Show details (*japanese only)"; var labelGoHere = "Go here"; var placeName = place.englishName; if (placeName === undefined || placeName === "") { placeName = place.name; } break; case "ko": var labelDeparture = "출발지 지정"; var labelArrival = "도착 지정"; var labelTreasure = "자세히보기 (*일본어 만)"; var labelGoHere = "여기로 이동"; var placeName = place.koreanName; if (placeName === undefined || placeName === "") { placeName = place.name; } break; case "zh-cn": var labelDeparture = "指定为出发地"; var labelArrival = "指定为目的地"; var labelTreasure = "查看详情 (*仅日语)"; var labelGoHere = "去这里"; var placeName = place.simplified_chineseName; if (placeName === undefined || placeName === "") { placeName = place.name; } break; case "zh-tw": var labelDeparture = "指定為出發地"; var labelArrival = "指定為目的地"; var labelTreasure = "查看詳細 (*僅日語)"; var labelGoHere = "去這裡"; var placeName = place.traditional_chineseName; if (placeName === undefined || placeName === "") { placeName = place.name; } break; case "th": var labelDeparture = "ตั้งเป็นออกเดินทาง"; var labelArrival = "กำหนดเป็นปลายทาง"; var labelTreasure = "ดูรายละเอียด (*ภาษาญี่ปุ่นเท่านั้น)"; var labelGoHere = "ไปที่นี่"; var placeName = place.thaiName; if (placeName === undefined || placeName === "") { placeName = place.name; } break; default: var labelDeparture = "出発地に指定"; var labelArrival = "到着地に指定"; var labelTreasure = "詳細を表示"; var labelGoHere = "ここに行く"; var placeName = place.name; } var html = ''; html += '
'; html += '
' + placeName + '
'; html += '
'; var $html = $(html); $html.find("a.setDeparture").click(function() { self.listeners["departureSelected"].forEach(function(func) { func({ type: type, placeName: placeName, code: place.code, lat: lat, lng: lng, }); }); self.setDepartureInfoWindow(lat, lng, placeName); self.departureInfoWindow.open(self.map); }); $html.find("a.setArrival").click(function() { self.listeners["arrivalSelected"].forEach(function(func) { func({ type: type, placeName: placeName, code: place.code, lat: lat, lng: lng, }); }); self.setArrivalInfoWindow(lat, lng, placeName); self.arrivalInfoWindow.open(self.map); }); $html.find("a.showTreasure").click(function() { $("#treasureDetail_title").html('' + placeName + ''); var treasureDetailHTML = '
' + placeName + '
'; treasureDetailHTML += '
' + place.address + '
'; if (place.comment !== undefined && place.comment != "") { treasureDetailHTML += '
' + place.comment + '
'; } treasureDetailHTML += ''; if (place.imageurl !== undefined && place.imageurl != "") { treasureDetailHTML += '
' + placeName + '
'; } $("#treasureDetail").html(treasureDetailHTML); $("#treasureDetailModal").modal('show'); }); self.infoWindow.setContent($html.get(0)); self.infoWindow.setPosition({ lat: lat, lng: lng }); self.infoWindow.open(self.map, marker); }, openInfoWindowByContent: function(lat, lng, html) { var self = this; self.infoWindow.setContent(html); self.infoWindow.setPosition({ lat: lat, lng: lng }); self.infoWindow.open(self.map); }, /** * ポップアップを閉じる */ closeInfoWindow: function() { var self = this; self.infoWindow.close(); }, /** * google.maps.Mapオブジェクトを返す */ getMap: function(latlng) { var self = this; return self.map; }, /** * 上部の「駅・バス停・施設名を入力」のテキストボックスを非表示にする */ hideTextbox: function() { var self = this; self.vm.showTextbox = false; }, /** * 経路探索が実行されたとき呼ばれる */ onArrivalStation: function(lat, lng, placeName) { var self = this; lat = parseFloat(lat); lng = parseFloat(lng); self.map.setCenter({ lat: lat, lng: lng }); self.map.setZoom(17); // 「到着地」ウィンドウを開く self.setArrivalInfoWindow(lat, lng, placeName, { addGoogleMapsRouteLink: true }); self.arrivalInfoWindow.open(self.map); self.hideTextbox(); }, setCenter: function(lat, lng, zoom) { var self = this; self.map.setCenter({ lat: lat, lng: lng }); }, setDepartureInfoWindow: function(lat, lng, placeName) { var self = this; var html = ''; html += '
'; html += '
' + VtmUtil.escapeHtml(placeName) + '
'; html += ' 出発地From출발지出发地出發地จุดออกเดินทาง'; html += '
'; self.departureInfoWindow.setContent(html); self.departureInfoWindow.setPosition({ lat: lat, lng: lng }); }, setArrivalInfoWindow: function(lat, lng, placeName, options) { var self = this; var html = ''; html += '
'; html += '
' + VtmUtil.escapeHtml(placeName) + '
'; html += ' 到着地To도착 지到达地到達地จุดมาถึง'; if (options && options.addGoogleMapsRouteLink) { // Google Mapsで現在地から到着地までの経路探索するURL var googleMapsRouteUrl = 'https://www.google.com/maps/dir/?api=1&destination=' + lat + ',' + lng; html += '
'; html += ' '; html += ' 現在地からの経路を見る'; html += ' Route from current location'; html += ' 현재 위치에서 경로보기'; html += ' 显示从当前位置出发的路线'; html += ' 顯示從當前位置出發的路線'; html += ' แสดงเส้นทางจากที่ตั้งปัจจุบัน'; html += ' '; html += '
'; } html += '
'; self.arrivalInfoWindow.setContent(html); self.arrivalInfoWindow.setPosition({ lat: lat, lng: lng }); }, };