PHPでSVGを使って年表を表示

(1/1)
ぱふぅ家のホームページのコーナー「日本史・世界史」では、XMLデータベースにある年表を、SVG (Scalable Vector Graphics)を用いてグラフィカルに表示している。
今回は、この部分のPHPプログラムを紹介する。

2017年(平成29年)10月、世界のどこでイベントが発生したかを俯瞰できるよう、Googleマップ上にマーカーを立てる機能を追加した。

(2022年4月9日)PHP8対応,リファラ・チェック改良

目次

サンプル・プログラムの実行例

PHPでSVGを使って年表を表示

サンプル・プログラム

圧縮ファイルの内容
viewChronologic.phpサンプル・プログラム本体
chronologic.xml年表ファイル

SVGとは何か

SVG とは "Scalable Vector Graphics" の略で、2Dのベクター画像記述言語として2001年(平成13年)にW3Cが公開した。HTMLへの組み込みも可能である。

公開当初はサポートしているブラウザが少なく、描画にはアドインが必要だったりしたことから普及が進まなかったが、HTML5ブラウザがサポートしたことからブレイク。アニメーション機能も備えていることから、Flashコンテンツの代替もできる。

ベクター描画であることから、画像を拡大縮小してもジャギーがあらわれないことが大きなメリットである。また、テキストの配置座標も細かく指定できるので、ブラウザによって表やグラフのレイアウトが崩れるという心配もない。
今回は利用していないが、レイヤー機能も備えている。

ぱふぅ家のホームページでは、年表のほか、当コーナーで表示しているXMLデータ構造やフローチャートをSVGを使って描画している。

準備

  34: //年表ファイル
  35: define('FILE_CHRONOLOGIC', 'chronologic.xml');
  36: 
  37: //年表(幅)
  38: define('CHRONOLOGIC_WIDTH', 600);
  39: 
  40: //インデント:左側
  41: define('CHRONOLOGIC_LEFT', 30);
  42: 
  43: //イベントの高さ
  44: define('CHRONOLOGIC_EVENT_HEIGHT', 34);
  45: 
  46: //年表地図(幅)
  47: define('CHRONOLOGICMAP_WIDTH', 600);
  48: 
  49: //年表地図(高さ)
  50: define('CHRONOLOGICMAP_HEIGHT', 350);
  51: 
  52: //ぱふぅ家のホームページ家のリンク・パス
  53: define('URL_PAHOO', 'https://www.pahoo.org/culture/numbers/year/');
  54: 
  55: //Googleマップ用マーカー・ファイルのパス;png限定
  56: define('PATH_MARKER', 'https://www.pahoo.org/common/marker/');
  57: 
  58: //Goole APIキー;各自の環境に合わせてください
  59: define('GOOGLE_API_KEY', '*******************************************');
  60: 
  61: //GoogleMapsの数
  62: $CountGoogleMaps = 1;
  63: 
  64: /**
  65:  * 表示フォントファミリー
  66:  * @global  double $ChronoFont
  67: */
  68: $ChronoFont = 'sans-serif';
  69: 
  70: /**
  71:  * ピクセル/年
  72:  * @global  double $ChronoPixelYear
  73: */
  74: $ChronoPixelYear = 0.0;
  75: 
  76: /**
  77:  * 開始年
  78:  * @global  int $ChronoStart
  79: */
  80: $ChronoStart = 0;

年表データは、下図の構造のXMLファイルとして用意し、そのファイル名は定数 FILE_CHRONOLOGIC に記述する。
この他、年表の幅や、表示フォント・ファミリーなど、各種の初期設定を定数に記述している。

XMLファイルに記述したリンク先ファイルは、定数 URL_PAHOO にあることを想定している。適宜書き換えていただきたい。
また、Googleマップに立てるマーカーは、定数 PATH_MARKER にあることを想定している。こちらも必要に応じて書き換えていただきたい。

Googleマップを利用するために Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を参照されたい。

解説:XMLファイル

XMLファイル(xml) chronologic record label イベント・人名 start 開始年 finish 終了年 latitude 緯度(世界測地系) longitude 経度(世界測地系) icon マップ用マーカー・ファイル名 filename リンク先ファイル名 description 記事

解説:配列へ格納

 174: /**
 175:  * 年表:XMLデータを配列へ格納
 176:  * @param   object $xml   年表:XMLデータ
 177:  * @param   array  $items 格納する配列
 178:  * @return  int 格納件数
 179: */
 180: function xml2array($xml, &$items) {
 181:     $cnt = 0;
 182:     foreach ($xml->record as $elm) {
 183:         $items[$cnt]['caption'] = '';
 184:         $items[$cnt]['label']   = '';
 185:         $items[$cnt]['event']   = '';
 186:         $items[$cnt]['caption'] =
 187:             isset($elm->caption? (string)$elm->caption : '';
 188:         $items[$cnt]['description'] =
 189:             isset($elm->description? (string)$elm->description : '';
 190:         if (isset($elm->label))     $ss = (string)$elm->label;
 191:         else if (isset($elm->event))    $ss = (string)$elm->event;
 192:         else if (isset($elm->name)) $ss = (string)$elm->name;
 193:         $items[$cnt]['label']  = isset($ss? $ss : '';
 194:         $items[$cnt]['start']  = isset($elm->start? (string)$elm->start : '';
 195:         $items[$cnt]['finish'] = isset($elm->finish? (string)$elm->finish  : '';
 196:         $items[$cnt]['filename'] = isset($elm->filename? (string)$elm->filename  : '';
 197:         $items[$cnt]['latitude'] = isset($elm->latitude? (double)$elm->latitude : '';
 198:         $items[$cnt]['longitude'] = isset($elm->longitude? (double)$elm->longitude : '';
 199:         $items[$cnt]['icon'] = isset($elm->icon? (string)$elm->icon : '';
 200:         $cnt++;
 201:     }
 202: 
 203:     return $cnt;
 204: }

ユーザー関数 xml2array は、定数 FILE_CHRONOLOGIC で指定した年表ファイル(XML形式)を読み込み、処理しやすいように配列に格納する。

解説:1つのイベントを作成

 372: /**
 373:  * 1つのイベントを作成する
 374:  * @param   array $item 年代記の要素
 375:  * @param   int   $y    Y座標
 376:  * @return  string SVG文字列
 377: */
 378: function mkchronologic_sub($item, $y, $id) {
 379:     global $ChronoPixelYear, $ChronoStart, $ChronoFont;
 380: 
 381:     $font_size = 12;        //描画テキストのフォント・サイズ
 382:     $start  = __chronoyear($item['start']);
 383:     $finish = __chronoyear($item['finish']);
 384: 
 385:     //$x1:バーの左端X座表  $width:バーの幅
 386:     //$x2:開始年のX座標  $x3:終了年のX座標
 387:     $x1 = (int)(CHRONOLOGIC_LEFT + ($start  - $ChronoStart* $ChronoPixelYear);
 388:     if ($start == $finish) {
 389:         $width = 5;
 390:         $item['start'] = '';
 391:         $x1 -5;
 392:         $x2 = $x1 + 5;
 393:     } else {
 394:         $width = (int)(($finish - $start* $ChronoPixelYear);
 395:         $x2 = $x1 - 5;
 396:     }
 397:     $x3 = $x1 + $width + 5;
 398: 
 399:     //イベントのラベル
 400:     if ($item['label'!'')           $label = $item['label'];
 401:     else if ($item['caption'!'')    $label = $item['caption'];
 402:     else                                $label = '';
 403: 
 404:     //ラベルの配置  $x4:ラベルのX座標
 405:     $len = mb_strlen($label);
 406:     //バーの中
 407:     if ($len * $font_size < $width) {
 408:         $x4 = (int)($x1 + ($width / 2));
 409:         $anchor = 'middle';
 410:     //バーの左
 411:     } else if ($item['start'] == '') {
 412:         $x4 = $x2 - $font_size * mb_strlen($item['start']) - 10;
 413:         $anchor = 'end';
 414:     } else {
 415:         $x4 = $x2 - $font_size * mb_strlen($item['start']);
 416:         $anchor = 'end';
 417:     }
 418:     //バーの右
 419:     if ($x4 - $len * $font_size <0) {
 420:         $x4 = $x3 + $font_size * mb_strlen($item['finish']);
 421:         $anchor = 'start';
 422:     }
 423:     $y1 = $y + 5;
 424:     $height = CHRONOLOGIC_EVENT_HEIGHT - 10;
 425:     $y2 = (int)($y1 + $height / 1.3);
 426: 
 427:     //ラベルとリンク
 428:     if (preg_match('/\.xml/', $item['filename']) > 0) {
 429:         $link = URL_PAHOO . preg_replace('/\.xml/', '.shtm', $item['filename']);
 430:         $color = '#0000FF';
 431:         $tooltip = 'サイト内リンク';
 432:     } else if ($label !'') {
 433:         $link = 'https://www.google.co.jp/search?q=' . urlencode($label);
 434:         $color = '#333333';
 435:         $tooltip = '外部リンク';
 436:     } else {
 437:         $link = '';
 438:         $color = '#000000';
 439:     }
 440:     if ($label !'') {
 441:         if ($link == '') {
 442:             $link =<<< EOT
 443: <text x="{$x4}" y="{$y2}" font-family="{$ChronoFont}" font-size="{$font_size}" fill="{$color}" text-anchor="{$anchor}" >{$label}</text>
 444: 
 445: EOT;
 446:         } else {
 447:             $link =<<< EOT
 448: <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{$link}">
 449: <text x="{$x4}" y="{$y2}" font-family="{$ChronoFont}" font-size="{$font_size}" fill="{$color}" text-anchor="{$anchor}" onmousemove="ShowTooltip(evt, '{$tooltip}', {$x1}, {$y1}, '')" onmouseout="HideTooltip(evt)" >{$label}</text>
 450: </a>
 451: 
 452: EOT;
 453:         }
 454:     }
 455: 
 456:     //バーとツールチップ
 457:     if ($item['description'!''$tooltip = $item['description'];
 458:     else                                $tooltip = '';
 459:     $str = sprintf('rect%04d', $id);
 460:     if ($tooltip == '') {
 461:         $bar =<<< EOT
 462: <rect id="{$str}" x="{$x1}" y="{$y1}" width="{$width}" height="{$height}" fill="#FFBB00" stroke="none" />
 463: 
 464: EOT;
 465:     } else {
 466:         $bar =<<< EOT
 467: <rect id="{$str}" x="{$x1}" y="{$y1}" width="{$width}" height="{$height}" fill="#FFBB00" stroke="none" onmousemove="ShowTooltip(evt, '{$tooltip}', {$x1}, {$y1}, '{$str}')" onmouseout="HideTooltip(evt)" />
 468: 
 469: EOT;
 470:     }
 471: 
 472:     $svg =<<< EOT
 473: {$bar}
 474: <text x="{$x2}" y="{$y2}" font-family="{$ChronoFont}" font-size="{$font_size}" fill="black" text-anchor="end">{$item['start']}</text>
 475: <text x="{$x3}" y="{$y2}" font-family="{$ChronoFont}" font-size="{$font_size}" fill="black" text-anchor="start">{$item['finish']}</text>
 476: {$link}
 477: 
 478: EOT;
 479: 
 480:     return $svg;
 481: }

ラベル
[Not supported by viewer]
バー
[Not supported by viewer]
開始年/終了年
[Not supported by viewer]
1つのイベントは、上図のように、ラベル、開始年/終了年、バーの3つの要素から構成される。ユーザー関数 mkchronologic_sub を使って描く。

まず、読み込んだデータには、たとえば生年が不明だったり、まだ存命の人物の場合には開始年/終了年が入っていない。そこで、ユーザー関数 __chronoyear を呼び出して、描画用のための仮年号を取得する。
次に、各要素の描画X座標 $x1$x3 やバーの幅 $width や高さ $height を計算する。
バーが短いときは、ラベルはバーの左側に配置。左側に配置して表枠外にはみ出すようだったら、バーの右側に配置するように座標計算する。

次にラベルを、SVGの text要素を使って描く。text-anchor属性を併用することで、バーに対してテキストを揃えている。
また、リンク先がある場合は、a要素を使ってハイパーリンクを張っている。

バーは、SVGの rect要素を使って描く。
description情報がある場合は、ツールチップを表示するようにした。ツールチップはJavaScriptで実装しており、「How to create an SVG “tooltip”-like box?」(Stack Overflow)の回答を参考にした。

最後に開始年と終了年を、SVGの text要素を使って描く。

解説:横軸を作成

 306: /**
 307:  * 横軸を作成する
 308:  * @param   array $items 年代記の要素
 309:  * @param   int   $width 年代記の横幅(単位:ピクセル,200以上)
 310:  * @return  string SVG文字列
 311: */
 312: function mkscale($items, $width, $height) {
 313:     global $ChronoPixelYear, $ChronoStart, $ChronoFont;
 314: 
 315:     //年の範囲
 316:     $year_min = +99999;
 317:     $year_max = -99999;
 318:     foreach ($items as $item) {
 319:         $year = __chronoyear($item['start']);
 320:         if ($year < $year_min)       $year_min = $year;
 321:         $year = __chronoyear($item['finish']);
 322:         if ($year > $year_max)      $year_max = $year;
 323:     }
 324: 
 325:     //年の範囲:丸め
 326:     $table = array(
 327:         array(1, 5),
 328:         array(2, 10),
 329:         array(5, 25),
 330:         array(10, 50),
 331:         array(15, 75),
 332:         array(25, 125),
 333:         array(50, 250),
 334:         array(100, 500),
 335:         array(150, 750),
 336:         array(200, 1000),
 337:         array(300, 1500),
 338:         array(400, 2000)
 339:     );
 340:     $period = $year_max - $year_min + 1;
 341:     foreach ($table as $arr) {
 342:         $delta = ($arr[0<25? $arr[0: 25;
 343:         if ($period <$arr[1]) {
 344:             $interval = $arr[0];
 345:             $start    = round($year_min  / $interval* $interval - $delta;
 346:             $finish   = round($year_max  / $interval* $interval + $delta;
 347:             break;
 348:         }
 349:     }
 350:     $ChronoPixelYear = ($width - 80) / ($finish - $start);
 351:     $ChronoStart = $start;
 352: 
 353:     $svg =<<< EOT
 354: <rect x="0" y="0" width="{$width}" height="{$height}" fill="none" stroke="#FFBB00" stroke-width="3" />
 355: <rect x="0" y="0" width="{$width}" height="30" fill="#FFBB00" stroke="none" />
 356: 
 357: EOT;
 358:     for ($year = $start$year <$finish$year +$interval) {
 359:         $x1 = (int)(CHRONOLOGIC_LEFT + ($year - $start* $ChronoPixelYear);
 360:         $x2 = $x1 - 15;
 361:         $y1 = 30;
 362:         $y2 = $height;
 363:         $svg .=<<< EOT
 364: <text x="{$x2}" y="25" font-family="{$ChronoFont}" font-size="14" fill="black" >{$year}</text>
 365: <line x1="{$x1}" y1="{$y1}" x2="{$x1}" y2="{$y2}" stroke="#FFDD88" stroke-width="1" />
 366: 
 367: EOT;
 368:     }
 369:     return $svg;
 370: }

年表の横軸を描画するのがユーザー関数 mkscale である。

まず、年表データの入った配列 $items を総なめして、開始年と終了年を抽出する。
次に横軸の目盛りの間隔を確定する。これは、配列変数 $table に定義している。第一要素が目盛りの間隔で、第二要素が描画期間(開始年~終了年の幅)である。この配列は自由に変更・増減できる。

横軸の背景はSVGの rect要素、目盛り line要素、年号はtext要素を使って、それぞれ描く。

解説:年表を作成

 206: /**
 207:  * 年表を作成する
 208:  * @param   array $info 年代記の要素
 209:  *                  string $items[]['caption']  = 棒グラフ上のキャプション
 210:  *                  string $items[]['label']    = 棒グラフ上のラベル
 211:  *                  int    $items[]['start']    = 開始年(生年)(必須)
 212:  *                  int    $items[]['finish']   = 終了年(没年)(必須)
 213:  *                  string $items[]['filename'] = リンク先ファイル名(XML)
 214:  * @return  string SVG文字列
 215: */
 216: function get_chronologic($items) {
 217:     $width  = CHRONOLOGIC_WIDTH;
 218:     $height = count($items* CHRONOLOGIC_EVENT_HEIGHT + 80;
 219:     $scale = mkscale($items, $width, $height);      //横軸作成
 220:     $table = mkchronologic($items, $width);     //年表作成
 221: 
 222:     $svg =<<< EOT
 223: <!-- 年表 -->
 224: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)" width="{$width}" height="{$height}">
 225: <style>
 226: .caption {
 227:     font-size: 14px;
 228:     font-family: Georgia, serif;
 229: }
 230: .tooltip {
 231:     font-size: 12px;
 232: }
 233: .tooltip_bg {
 234:     fill: white;
 235:     stroke: black;
 236:     stroke-width: 1;
 237:     opacity: 0.85;
 238: }
 239: </style>
 240: 
 241: <script type="text/ecmascript">
 242: <![CDATA[
 243: function init(evt) {
 244:     if (window.svgDocument == null) {
 245:         svgDocument = evt.target.ownerDocument;
 246:     }
 247:     tooltip = svgDocument.getElementById('tooltip');
 248:     tooltip_bg = svgDocument.getElementById('tooltip_bg');
 249: }
 250: 
 251: function ShowTooltip(evt, mouseovertext, x, y, id) {
 252:     tooltip.setAttributeNS(null,"x",evt.clientX + 11);
 253:     tooltip.setAttributeNS(null,"y",y + 27);
 254:     tooltip.firstChild.data = mouseovertext;
 255:     tooltip.setAttributeNS(null,"visibility","visible");
 256: 
 257:     length = tooltip.getComputedTextLength();
 258:     tooltip_bg.setAttributeNS(null,"width",length + 8);
 259:     tooltip_bg.setAttributeNS(null,"x",evt.clientX + 8);
 260:     tooltip_bg.setAttributeNS(null,"y",y + 14);
 261:     tooltip_bg.setAttributeNS(null,"visibility","visibile");
 262: }
 263: 
 264: function HideTooltip(evt) {
 265:     tooltip.setAttributeNS(null,"visibility","hidden");
 266:     tooltip_bg.setAttributeNS(null,"visibility","hidden");
 267: }
 268: ]]>
 269: </script>
 270: 
 271: {$scale}
 272: {$table}
 273: 
 274: <rect class="tooltip_bg" id="tooltip_bg"
 275:       x="0" y="0" rx="4" ry="4"
 276:       width="55" height="17" visibility="hidden"/>
 277: <text class="tooltip" id="tooltip"
 278:       x="0" y="0" visibility="hidden">Tooltip</text>
 279: </svg>
 280: 
 281: EOT;
 282: 
 283:     return $svg;
 284: }

年表作成の本体は、get_chronologic である。
ユーザー関数 mkscalemkchronologic を呼び出し年表を描画する。

また、ツールチップを表示するためのJavaScriptも記述してある。

解説:年表地図を作成

 509: /**
 510:  * 年表地図を作成する
 511:  * @param   array $info 年代記の要素
 512:  *                  string $items[]['caption']   = 棒グラフ上のキャプション
 513:  *                  string $items[]['label']     = 棒グラフ上のラベル
 514:  *                  int    $items[]['start']     = 開始年(生年)(必須)
 515:  *                  int    $items[]['finish']    = 終了年(没年)(必須)
 516:  *                  double $items[]['latitude']  = 緯度
 517:  *                  double $items[]['longitude'] = 経度
 518:  *                  string $items[]['icon']      = マーカー・ファイル名(拡張子は除く)
 519:  *                  double $items[]['description'] = 記事
 520:  *                  string $items[]['filename']  = リンク先ファイル名(XML)
 521:  * @return  string HTMLテキスト
 522: */
 523: function get_chronologicalmap($items) {
 524:     global $CountGoogleMaps;
 525: 
 526:     $apikey = GOOGLE_API_KEY;
 527:     $width  = CHRONOLOGICMAP_WIDTH;
 528:     $height = CHRONOLOGICMAP_HEIGHT;
 529:     $mode   = 'ROADMAP';
 530:     $zoom   = 1;
 531:     $lat = '';
 532:     $lng = '';
 533:     $js  = ($CountGoogleMaps > 1? '' :
 534:         "<script type=\"text/javascript\" src=\"https://maps.google.com/maps/api/js?key={$apikey}&amp;region=JP\"></script>";
 535: 
 536:     $flag = FALSE;
 537:     $str = '';
 538:     $arrs = array();
 539:     foreach ($items as $item) {
 540:         if (($item['latitude'!''&& ($item['longitude'!'')) {
 541:             $key = $item['latitude'.',' . $item['longitude'];
 542:             if (! $flag) {
 543:                 //中心座標
 544:                 $lat = (double)$item['latitude'];
 545:                 $lng = (double)$item['longitude'];
 546:                 $flag = TRUE;
 547:             }
 548:             //ラベルとリンク
 549:             if (preg_match('/\.xml/', $item['filename']) > 0) {
 550:                 $link = URL_PAHOO . preg_replace('/\.xml/', '.shtm', $item['filename']);
 551:                 $color = '#0000FF';
 552:                 $tooltip = 'サイト内リンク';
 553:             } else if ($label !'') {
 554:                 $link = 'https://www.google.co.jp/search?q=' . urlencode($label);
 555:                 $color = '#333333';
 556:                 $tooltip = '外部リンク';
 557:             } else {
 558:                 $link = '';
 559:                 $color = '#000000';
 560:             }
 561:             //年号
 562:             $year = ($item['start'] == $item['finish']) ? $item['start']:
 563:                 $item['start'. ' - ' . $item['finish'];
 564:             //マーカー
 565:             $marker = (isset($item['icon']) && ($item['icon'!'')) ? PATH_MARKER . $item['icon'.'.png' : PATH_MARKER . 'history.png';
 566:             //配列へ代入
 567:             $arrs[$key]['latitude']  = $item['latitude'];
 568:             $arrs[$key]['longitude'] = $item['longitude'];
 569:             $arrs[$key]['title']     = $item['label'];
 570:             $label = ($link == ''? "<span style=\"color:blue;\"{$item['label']}" : "<a href=\"{$link}\" target=\"_blank\">{$item['label']}</a>";
 571:             $description = ($item['description'] == ''? '' : "‥‥{$item['description']}";
 572:             $content = "<p style=\"text-align:left;\">{$label}&nbsp;({$year}年)<span style=\"font-size:80%;\">{$description}</span></p>";
 573:             //重複イベントはスキップ
 574:             if (isset($arrs[$key]['content'])) {
 575:                 if (mb_strstr($arrs[$key]['content'], $content) == FALSE) {
 576:                     $arrs[$key]['content'.$content;
 577:                 }
 578:             } else {
 579:                 $arrs[$key]['content'] = $content;
 580:             }
 581:             $arrs[$key]['marker'] = $marker;
 582:         }
 583:     }
 584: 
 585:     //JavaScript生成
 586:     $str = '';
 587:     $n = 1;
 588:     foreach ($arrs as $arr) {
 589:         $str .<<< EOT
 590: var icon_{$n} = new google.maps.MarkerImage('{$arr['marker']}');
 591: var marker_{$n} = new google.maps.Marker({
 592:     position: new google.maps.LatLng({$arr['latitude']}, {$arr['longitude']}),
 593:     map: map,
 594:     icon: icon_{$n},
 595:     title: '{$arr['title']}',
 596:     zIndex: 250
 597: });
 598: var infowindow_{$n} = new google.maps.InfoWindow({
 599:     content: '{$arr['content']}',
 600:     size: new google.maps.Size(200, 100)
 601: });
 602: google.maps.event.addListener(marker_{$n}, 'click', function() {
 603:     infowindow_{$n}.open(map, marker_{$n});
 604: });
 605: 
 606: EOT;
 607:         $n++;
 608:     }
 609:     //地図情報がない
 610:     if (($lat == ''|| ($lng == ''))   return '';
 611: 
 612:     $dest =<<< EOT
 613: {$js}
 614: <script type="text/javascript">
 615: <!--
 616: google.maps.event.addDomListener(window, 'load', function() {
 617: var mapdiv = document.getElementById('gmap{$CountGoogleMaps}');
 618: var myOptions = {
 619:     zoom: {$zoom},
 620:     center: new google.maps.LatLng({$lat}, {$lng}),
 621:     mapTypeId: google.maps.MapTypeId.{$mode},
 622:     mapTypeControl: false,
 623:     scaleControl: true
 624: };
 625: var map = new google.maps.Map(mapdiv, myOptions);
 626: {$str}
 627: 
 628: });
 629: -->
 630: </script>
 631: <div style="margin-bottom:20px;">
 632: <div id="gmap{$CountGoogleMaps}" style="width:{$width}px; height:{$height}px;">
 633: </div>
 634: </div>
 635: 
 636: EOT;
 637:     $CountGoogleMaps++;
 638: 
 639:     return $dest;
 640: }

年表地図の本体は、get_chronologicalmap である。
GooleMaps API の使い方は「PHPで地図で指定した場所の天気予報を求める」などで解説しているので、あわせてご覧いただきたい。

冒頭で、Googleマップの縦・横のサイズと、モード $mode、ズーム $zoom を指定している。

次に、引数として与えられた年表情報配列 $items を1つずつ解析していく。
地図の中心は、最初の要素の位置情報を採用する。

参考サイト

(この項おわり)
header