Google Maps JavaScript API V3 を用いたマーカー表示

by Madoka Fukahori on 1月 13, 2011 at 04:37 午後

V3からAPIキーが不要になったGoogle Maps JavaScript API V3を利用して、
Salesforce内のデータを地図上にマーカー表示するサンプルをご紹介します。

Gmapsample1_2

今回ご紹介するのは,Salesforceの取引先データに格納されている住所データを用いてGoogleMapへプロットするVisualforceコンポーネントです。取引先の詳細画面から現在表示している取引先の場所とその周辺にある取引先の位置情報が確認できます。

下記のサンプルコードのようなVisualforceと拡張コントローラを作成後に、取引先の詳細ページのページレイアウトにコンポーネントを追加します。

Gmapsample2

今回は周囲の取引先データを表示していますが、Force.com上に任意のデータベースを作り、 それらのデータを下記の方法でJSONデータとして取得し、表示することで施設情報の地図などを簡単に作ることができます。

是非色々とお試しください。

サンプルコード( Visualforce)


<apex:page showHeader="false" sidebar="false" standardController="Account" extensions="CntNearByAccount">
<head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function() {
var mapOptions = {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true
};
var mapObj = new google.maps.Map(document.getElementById('gmap'), mapOptions);
var request = {
address: '{!Account.BillingPostalCode} + {!Account.BillingState} + {!Account.BillingCity} + {!Account.BillingStreet}'
};
// 表示取引先をジオコーディング
var ACgeocoder = new google.maps.Geocoder();
ACgeocoder.geocode(request, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
mapObj.setCenter(results[0].geometry.location);
// マーカーを表示
var marker = new google.maps.Marker({
position: results[0].geometry.location, // 表示取引先を中心に表示
title: request.address,
map: mapObj
});
// ポップアップ内の情報
var ACinfoWindow = new google.maps.InfoWindow();
var ACHTMLinfo = '<a target=\"_top\" href=\"/{!Account.Id}\">{!Account.Name}</a><br/>{!Account.BillingState}{!Account.BillingCity}{!Account.BillingStreet}';
ACinfoWindow.setContent(ACHTMLinfo);
ACinfoWindow.setPosition(results[0].geometry.location);
// マップクリックイベントを追加
google.maps.event.addListener(marker, 'click', function(){
ACinfoWindow.open(mapObj,marker);
});
}
});
// 周囲の取引先情報を取得
var ACdata ={
list: {!accountsData},
// Getter
getAll: function(){
return this.list;
}
};
// マーカー画像を作成
var markerImg = new google.maps.MarkerImage(
// マーカーの画像URL
"{!URLFOR($Resource.AC_icon)}",
// マーカーのサイズ
new google.maps.Size(30, 30),
// 画像の基準位置
new google.maps.Point(0, 0),
// Anchorポイント
new google.maps.Point(0, 0)
);
// マーカー影画像
var shadow = new google.maps.MarkerImage(
//影画像URL
"{!URLFOR($Resource.AC_shadow)}",
// マーカーのサイズ
new google.maps.Size(43, 38),
// 画像の基準位置
new google.maps.Point(0, 0),
// Anchorポイント
new google.maps.Point(0, 5)
);
var shape = {
coord: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
// マーカーを作成
jQuery.each(ACdata.getAll(), function(i, ACdata) {
// ジオコーディング
var address = ACdata.address;
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
// ステータスがOKならマーカーを表示する。
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: mapObj,
shadow: shadow,
icon: markerImg,
shape: shape,
title: ACdata.name,
zIndex : 0
});
// ポップアップ内の情報
var infoWindow = new google.maps.InfoWindow();
var HTMLinfo = '<a target=\"_top\" href=\"/' + ACdata.id + '\">' + ACdata.name + '</a><br/>' + ACdata.info;
infoWindow.setContent(HTMLinfo);
infoWindow.setPosition(results[0].geometry.location);
// マップクリックイベントを追加
google.maps.event.addListener(marker, 'click', function(){
infoWindow.open(mapObj,marker);
});
}
});
});
});
</script>
</head>
<body>
<div id="gmap" style="height:300px;width: 500px;"></div>
</body>
</apex:page>

サンプルコード( Apex)

public with sharing class CntNearByAccount {
    public Account a{get;set;}
    public CntNearByAccount(ApexPages.StandardController stdController) {
        a = (Account)stdController.getRecord();
    }
    public Object[] getAccountsData(){
        Object[] jsonData = new Object[]{};
        // 表示取引先以外を取得
        for(Account AccountsData : [SELECT Id, Name, BillingStreet, BillingCity, BillingState, BillingPostalCode 
            FROM Account where Id != :a.Id]){ 
            jsonData.add(
                '{name:\'' + AccountsData.Name + 
                    '\', address:\'' + AccountsData.BillingPostalCode + AccountsData.BillingState + AccountsData.BillingCity + AccountsData.BillingStreet + 
                    '\', id:\'' + AccountsData.Id + 
                    '\', info:\'' + AccountsData.BillingState + AccountsData.BillingCity + AccountsData.BillingStreet + 
                '\'}'
            );
        }
        return jsonData;
    } 
}

トラックバック

このページのトラックバックURL: http://www.typepad.jp/t/trackback/7240/25748456

このページへのトラックバック一覧 Google Maps JavaScript API V3 を用いたマーカー表示:

コメント

Posted by 関根 利彦 on 7月 1, 2011 11:05 午前:

JSONデータについて教えてください。
CntNearByAccountのコードを読むと
JSONと名前のオブジェクトを作成して、取引先の名前・住所を数式項目で作成したもののように見えるのですが、それでよろしいのでしょうか。

Posted by Madoka Fukahori on 7月 1, 2011 11:20 午前:

JSONデータとしては取引先の名前(name)、住所(address)、Id(id)、ポップアップ表示用の住所情報(info)を取得しています。取引先のオブジェクトは郵便番号、都道府県、市区郡、町名・番地はそれぞれ別の項目として持っていますのでJSONデータとして住所情報を作成する際に下記のように文字列を連結させています。
AccountsData.BillingPostalCode + AccountsData.BillingState + AccountsData.BillingCity + AccountsData.BillingStreet

取引先を利用するのではなく、カスタムオブジェクトで独自の住所項目を作成した場合は、このような文字列連結の必要はないと思います。(フォームの作り方次第です)

ご不明な点がございましたらお知らせください。

Posted by R.N on 12月 14, 2011 11:14 午前:

Google Maps APIの利用規約をみると、アクセス制限の掛かったサイトなどで使用するにはGoogle Maps API Premier(有償)が必要とあります。

http://googleenterprise-ja.blogspot.com/2010/03/google-maps-apigoogle-maps-api-premier.html

当記事のサンプルにあるような使い方をする場合に、Salesforceと契約している組織側でGoogle Maps API Premier(有償)の契約が必要になるのでしょうか?

Posted by 寺田克彦 on 1月 24, 2012 09:40 午後:

jsonDataに格納される件数について教えてください。
SOQLの結果は、30件ほどあるのですが、表示される周囲の取引先情報が10件しか表示されません。表示件数を増やすにはどのようにすればよろしいでしょうか?

Posted by Madoka Fukahori on 1月 26, 2012 08:20 午後:

Google Maps API は、昨年規約が変わり、パブリックなウェブページでの使用に限って無償使用が許諾されている模様です。
クローズドな環境での使用については、グーグル様との有償契約が発生する 場合がございます。
詳細についてはグーグル様にお問い合わせいただきますようお願い致します。

Posted by Madoka Fukahori on 1月 26, 2012 08:27 午後:

>jsonDataに格納される件数について教えてください。
SOQLの結果は、30件ほどあるのですが、表示される周囲の取引先情報が10件しか表示されません。表示件数を増やすにはどのようにすればよろしいでしょうか?

こちらについてですが、表示領域を大きくするか表示を広域にするのはいかがでしょうか。データとして取得をしていても、住所情報の位置が表示取引先の位置より遠い場合は表示範囲の都合上、表示されない形になります。
あるいは、ロジックを追加して半径5km内の取引先のみ表示するような開発を行うのはいかがでしょうか。

コメントを投稿

コメントは記事の投稿者が承認するまで表示されません。