Apex での地図データの作成例
カスタムクエリの実行、近くの場所の検索、結果の絞り込みや変換を行う場合、または Visualforce の標準コントローラから返される結果を使用できない場合は、Apex で場所データを作成します。
Apex コードでは、返される結果を完全に制御して、地図やマーカーに使用できます。また、Apex を使用して、Salesforce 外から結果を返すこともできます。
次のページには、ユーザの現在の場所に最も近い最大 10 個の倉庫が表示されます。
このコードにより、次の地図が作成されます。
1<apex:page controller="FindNearbyController" docType="html-5.0" >
2
3 <!-- JavaScript to get the user's current location, and pre-fill
4 the currentPosition form field. -->
5 <script type="text/javascript">
6 // Get location, fill in search field
7 function setUserLocation() {
8 if (navigator.geolocation) {
9 navigator.geolocation.getCurrentPosition(function(loc){
10 var latlon = loc.coords.latitude + "," + loc.coords.longitude;
11 var el = document.querySelector("input.currentPosition");
12 el.value = latlon;
13 });
14 }
15 }
16 // Only set the user location once the page is ready
17 var readyStateCheckInterval = setInterval(function() {
18 if (document.readyState === "interactive") {
19 clearInterval(readyStateCheckInterval);
20 setUserLocation();
21 }
22 }, 10);
23 </script>
24
25 <apex:pageBlock >
26 <!-- Form field to send currentPosition in request. You can make it
27 an <apex:inputHidden> field to hide it. -->
28 <apex:pageBlockSection >
29 <apex:form >
30 <apex:outputLabel for="currentPosition">Find Nearby</apex:outputLabel>
31 <apex:input size="30"
32 html-placeholder="Attempting to obtain your position..."
33 id="currentPosition" styleClass="currentPosition"
34 value="{!currentPosition}" />
35 <apex:commandButton action="{!findNearby}" value="Go!"/>
36 </apex:form>
37 </apex:pageBlockSection>
38
39 <!-- Map of the results -->
40 <apex:pageBlockSection rendered="{!resultsAvailable}" title="Locations">
41 <apex:map width="600px" height="400px">
42 <apex:repeat value="{!locations}" var="pos">
43 <apex:mapMarker position="{!pos}"/>
44 </apex:repeat>
45 </apex:map>
46 </apex:pageBlockSection>
47
48 </apex:pageBlock>
49
50</apex:page>
このページには、3 つの重要なセクションがあります。
- 先頭にある JavaScript ブロックは、ユーザの現在の場所を要求するブラウザの組み込み機能へのアクセス方法を示します。このコードが表示されるフォーム項目を更新します。もちろん非表示のフォーム項目を使用することもでき、その場合は未加工の緯度と経度が低い精度で表示されるのを簡単に回避できます。
- 最初の <apex:pageBlockSection> には、ユーザの場所を POSTBACK 要求に送信するための簡単なフォームが含まれています。説明のため、フォームが表示されクリックを必要とする設定になっていますが、これは必須ではありません。
- 2 番目の <apex:pageBlockSection> は、わずか 5 行のコードを必要とする簡単な地図です。複雑な点は、Apex コントローラでプロパティにアクセスする {!locations} 式のみです。
{!resultsAvailable} 式の値を取得する rendered 属性の使用に注目してください。この式は別の Apex プロパティであり、rendered 属性と共に使用すると、地図に配置できる場所がなければ、地図セクションが非表示になります。
次に、上記のページをサポートする Apex コントローラを示します。
1public with sharing class FindNearbyController {
2
3 public List<Map<String,Double>> locations { get; private set; }
4
5 public String currentPosition {
6 get {
7 if (String.isBlank(currentPosition)) {
8 currentPosition = '37.77493,-122.419416'; // San Francisco
9 }
10 return currentPosition;
11 }
12 set;
13 }
14
15 public Boolean resultsAvailable {
16 get {
17 if(locations == Null) {
18 return false;
19 }
20 return true;
21 }
22 }
23
24 public PageReference findNearby() {
25 String lat, lon;
26
27 // FRAGILE: You'll want a better lat/long parsing routine
28 // Format: "<latitude>,<longitude>" (must have comma, but only one comma)
29 List<String> latlon = currentPosition.split(',');
30 lat = latlon[0].trim();
31 lon = latlon[1].trim();
32
33 // SOQL query to get the nearest warehouses
34 String queryString =
35 'SELECT Id, Name, Location__longitude__s, Location__latitude__s ' +
36 'FROM Warehouse__c ' +
37 'WHERE DISTANCE(Location__c, GEOLOCATION('+lat+','+lon+'), \'mi\') < 20 ' +
38 'ORDER BY DISTANCE(Location__c, GEOLOCATION('+lat+','+lon+'), \'mi\') ' +
39 'LIMIT 10';
40
41 // Run the query
42 List <Warehouse__c> warehouses = database.Query(queryString);
43
44 if(0 < warehouses.size()) {
45 // Convert to locations that can be mapped
46 locations = new List<Map<String,Double>>();
47 for (Warehouse__c wh : warehouses) {
48 locations.add(
49 new Map<String,Double>{
50 'latitude' => wh.Location__latitude__s,
51 'longitude' => wh.Location__longitude__s
52 }
53 );
54 }
55 }
56 else {
57 System.debug('No results. Query: ' + queryString);
58 }
59
60 return null;
61 }
62}このコントローラの詳細および Visualforce ページでどのように動作するかを習得してください。
- locations プロパティは、Map<String,Double> 要素のリストです。このリストには、<apex:mapMarker> コンポーネントで直接使用できる形式で場所データが保持されます。
- currentPosition プロパティは、ページのフォームから送信された位置情報を取得します。このプロパティにも、空のフォームが送信された場合には有効なデフォルト値が提供されます(堅牢な実装にすることで、フォーム入力に対するエラーチェックが強化されます)。
- Visualforce マークアップの以前の説明で記載した resultsAvailable プロパティ。
- findNearby アクションメソッドは、[Go!] <apex:commandButton> が押されるとコールされます。このメソッドは、カスタム SOQL クエリの実行、locations プロパティ形式への結果の変換など、すべての処理を行います。
<apex:mapMarker> の title 属性を使用して追加の情報 (倉庫の名前など) を提供する場合は、いくつかのオプションがあります。メソッドが sObject を返す場合は、Visualforce マークアップで適切な項目を参照できます。この例と同様に、新しいオブジェクトを直接作成する場合は、場所を示す地図オブジェクトとタイトル文字列を組み合わせる内部クラスを作成できます。これにより内部クラスオブジェクトのコレクションがページに返されます。