この記事は concrete5 Japan Advent Calendar 2016 の21日目の記事でございます。
昨日はfujigoco2255さんの「concrete5の導入事例をインフォグラフィックにしてみた」でしたね。
マーケターさん目線での非常にためになる記事でした。しびれる記事。読むべし!
はい、concrete5並びにそこに携わる皆さんには今年も大変お世話になりました。
飲みに行ったり、エバンジェリストになったり、飲みに行ったり、こないだ京都の皆でconcrete5の日を開催したり、飲みに行ったりとか色々なことがありました。
来年もたくさん飲みに行きましょう!
去年はconcrete5の思い出的な記事を書いたので今年はちょっとだけ技術tips的なことを。
「ページリストブロック + Google Maps APIをカスタマイズしてイベントマップを作る」をやります。
※concrete5中級者?向け記事かと
※ホントはパッケージからページタイプ・ページ属性を登録して〜とかやりたかったんですが、
いかんせん師走につきブロックのカスタマイズのところだけ駆け足で行きます!
【こんなことします】
イベント告知ページを作ってページ属性に緯度・経度を登録してイベント一覧ページにpage_listブロックを設置。イベントリストを表示。
ページリストを使って出力されたイベントリストの上部に登録したイベント開催場所が全部表示されたGoogle Mapを出力する。
【必要なもの】
・concrete5
・Google Maps APIのAPIキー(←取得しといてね)
・concrete5のブロックカスタマイズに関する少しの知識
※APIキーの取得手順についてはこちらがわかりやすいです。
『Google Maps の APIキー を簡単に取得する』
https://nendeb.com/276
まずは一覧表示ページを作ってページリストを設置しておきます。
「場所」は「ここのページ以下の階層」を指定して、このページの配下にイベント情報を投稿していきましょう。
続いてページ属性を用意します。
「テキスト」タイプで緯度・経度の登録用項目を用意します。
下準備として、先ほど登録した一覧表示ページ配下に適当な緯度・経度データを入れたページを追加しておきます。
続いてテンプレートのカスタマイズ準備です。
/concrete/blocks/page_list/controller.php を
/application/blocks/page_list/controller.php へコピー。
viewテンプレートとして
/application/blocks/page_list/view.php を
/application/blocks/page_list/templates/event_map/view.php へコピー
しておきましょう。
/application/blocks/page_list/controller.phpのカスタマイズを進めます。
まずはお作法通りファイル冒頭のnamespaceを書き換え。
|
namespace Application\Block\PageList; |
このタイミングでカスタムテンプレートが選択できるようになるので
先ほど設置したブロックにカスタムテンプレートを設定しておきます。
続いてマップの表示に必要なjsライブラリを読み込ませます。
class Controller の末尾にこちらを追加。
|
public function registerViewAssets($outputContent = '') { $this->requireAsset('javascript', 'jquery'); $this->requireAsset('javascript', 'underscore'); $c = Page::getCurrentPage(); if (!$c->isEditMode()) { $this->addFooterItem( '<script defer src="https://maps.googleapis.com/maps/api/js?key=' . 'ここにAPIキー' .'"></script>' ); } } |
マップ出力に必要なjQueryとunderscore.jsを読み込ませます。
さらにGoogle Maps API読み込みもここで設定。取得済みのAPIキーを入力します。
※underscore使わなくてもできますが、コアに登録されてるjsはconcrete5の処理を通すことで自由に呼び出して且つ重複を気にせず扱えますよーアピールで。
※ホントはAPIキーをブロックの登録時にconfigとかに保存する方が良いと思います。google mapブロックのcontrollerが参考になります。
ページリストが1ページ内に複数設置されることも想定して、
設置されたブロックごとにマップ関連の機能が利用できるような判定材料を入れます。
viewメソッドにこちらを追加。
|
public function view() { $this->set('unique_identifier', Core::make('helper/validation/identifier')->getString(18)); //以下略 } |
これで生成される文字列をviewテンプレート内の処理でIDの一部として扱います。
続いてviewテンプレートのカスタマイズへ。
/application/blocks/page_list/templates/event_map/view.php
6行目に追加
マップの緯度経度を格納する配列を設定しておきます。
/application/blocks/page_list/templates/event_map/view.php
8行目に追加
|
<div id="map_canvas_<?php echo $unique_identifier?>"></div> |
マップ表示用の要素を設置します。
$unique_identifier込みでidを振って同じページに同ブロック同テンプレートが複数設置される場合にも対応します。(後述のjs処理も同様)
続いてforeachでページデータを出力する流れでマップ表示用のデータを作っていきます。
/application/blocks/page_list/templates/event_map/view.php
141行目に追加
|
$map_data[] = array( 'title' => $title, 'url' => $url, 'lat' => $page->getAttribute('lat'), 'lng' => $page->getAttribute('lng') ); |
ページタイトルとページURLはページリストの処理から拝借します。
ページ属性から緯度・経度も取得して配列にまとめます。
さ、準備は万端。マップの出力処理です。
/application/blocks/page_list/templates/event_map/view.php
末尾に追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
<?php $js = Core::make('helper/json');?> <script> var event_data_<?php echo $unique_identifier?> = <?php echo $js->encode($map_data);?>; function map_gen_<?php echo $unique_identifier?>(data){ /* =============================================== mapの初期表示 =============================================== */ var currentInfoWindow; var map = null; var options = { zoom:12, center:new google.maps.LatLng(35.0116363,135.76802939999993), mapTypeId:google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas_<?php echo $unique_identifier?>"),options); if(data.length === 0){ return; } /* =============================================== marker出力 =============================================== */ _.each(data,function(item,index){ var title = item.title; var marker = {}; var obj = { position:new google.maps.LatLng(item.lat,item.lng), map:map, title:item.title }; marker = new google.maps.Marker(obj); /* =============================================== クリックイベント =============================================== */ //吹き出し内のhtml var inner = '<article class="mapinner" style="width:400px;">' + '<h4>'+item.title+'</h4><a href="'+item.url+'">詳細はこちらだ!</a></article>'; //マップのクリックイベントに吹き出しを開く機能をバインド google.maps.event.addListener(marker, 'click', function(event) { if (currentInfoWindow) { currentInfoWindow.close(); } var infoWnd = new google.maps.InfoWindow({content: inner, maxWidth: 600}); infoWnd.open(marker.getMap(), marker); currentInfoWindow = infoWnd; //中心に位置を修正する map.setCenter(marker.getPosition()); }); }); } (function($) { $(function(){ map_gen_<?php echo $unique_identifier?>(event_data_<?php echo $unique_identifier?>); }); })(jQuery); </script> |
ポイントはこのあたり。
ページリストの処理に乗っかって作ったマップ表示用データをjsonに変換してます。
|
<?php $js = Core::make('helper/json');?> |
|
var event_data_<?php echo $unique_identifier?> = <?php echo $js->encode($map_data);?>; |
このjsonをunderscoreの_.eachで回してマップにピンを立てていきます。
※マップ出力についての説明は割愛します。今回は最低限の設定のみで。
|
_.each(data,function(item,index){ //以下略 } |
完成品はこちら。
http://suitosha.co.jp/temporary/c5sample/events
登録したページの緯度経度に応じてマップにピンが追加されてます。
マーカーをクリックして詳細ページへのリンク付き吹き出しを出す処理も追加してます。
コードの全容は取り急ぎこちらからどうぞ!
page_listブロックをカスタマイズしてページ属性で登録された緯度・経度からGoogle Mapにピンを立てるサンプル
超駆け足でしたがブロックの処理にちょっと工夫するだけで便利な機能作れまっせ〜ということです!
concrete5はブロック側のphpからjsへの橋渡しをし易くする機能がそこかしこに用意されているので嬉しいです。
最近リリースされたconcrete5 version 8に搭載されているExpress Data Objectsでは
より細か〜いデータの管理がしやすくなるので、
サイトに登録されたデータをjsで面白おかしく加工したりとか考えるとわくわくしますね。
しますよね??
というわけで来年も公私ともにお世話になりますconcrete5!
明日22日は、全国数万人のconcrete5erお待ちかね、
今年数多の登壇で各地に笑いとか笑いとか感動とかを巻き起こした
カリスマデザイナーことDJ Kazu氏の出番です。
彗星のごとくconcrete5に現れたWebデザイナーの1年
Kazuくん、今年は美味しいお店たくさん教えてくれてありがとう。
個人的にconcrete5 T-shirtsのスウェット版欲しいので是非、来年企画にあげてください。
みなさま、師走を頑張って生き延びて!良いお年を〜!