データの可視化


<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      #map {
        height: 50%;
        margin-top: 10px;
      }
      html, body {
        height: 100%;
        margin: 10px;
        padding: 0;
      }
    </style>
  </head>
  <body>
  	<div id="map"></div>
  	<script>
  	var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          zoom: 2,
          center: {lat: -33.865427, lng: 151.196123},
          mapTypeId: 'terrain'
        });

      var script = document.createElement('script');
      script.src = 'https://developers.google.com/maps/documentation/javascript/examples/json/earthquake_GeoJSONP.js';
        document.getElementsByTagName('head')[0].appendChild(script);

        map.data.setStyle(function(feature) {
          var magnitude = feature.getProperty('mag');
          return {
            icon: getCircle(magnitude)
          };
        });
      }

      function getCircle(magnitude) {
        return {
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: 'red',
          fillOpacity: .2,
          scale: Math.pow(2, magnitude) / 2,
          strokeColor: 'white',
          strokeWeight: .5
        };
      }

      function eqfeed_callback(results) {
        map.data.addGeoJson(results);
      }


      // // window.eqfeed_callback = function(results) {
      // //   for (var i = 0; i < results.features.length; i++) {
      // //     var coords = results.features&#91;i&#93;.geometry.coordinates;
      // //     var latLng = new google.maps.LatLng(coords&#91;1&#93;,coords&#91;0&#93;);
      // //     var marker = new google.maps.Marker({
      // //       position: latLng,
      // //       map: map
      // //     });
      // //   }
      // }
    </script>
  	<script async defer
src="https://maps.googleapis.com/maps/api/js?key=notwatch&callback=initMap">
</script>
</body>
</html>

google map ROADMAP, SATELLITE, HYBRID, TERRAIN

丹下健三でもみてみましょう。
まず、デフォルトのROADMAP

function initMap(){
      var position = {lat: <?php echo $lat_a; ?>, lng: <?php echo $lng_a; ?>};
  		map = new google.maps.Map(document.getElementById('map'),{
  			center: position,
  			zoom: 14,
        // mapTypeId: 'terrain'
  		});

続いて、satellite
大文字だと表示されません。

次は、hybrid

最後に、terrain

結論は、生で見よう。

document.createElement(‘script’);

bodyにscriptを追加。

var script = document.createElement('script');
script.src = 'http://example.com/hoge.js';
document.body.appendChild(script);

window.はdomを収める

mapTypeId: ‘terrain’ 地形情報を使った地図
ROADMAP 道路や建物
SATELITE 衛星写真
HyBRID ROADMAPとSATELITE
TERRAIN 地形情報

デフォルトはROADMAP

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      #map {
        height: 50%;
        margin-top: 10px;
      }
      html, body {
        height: 100%;
        margin: 10px;
        padding: 0;
      }
    </style>
  </head>
  <body>
  	<div id="map"></div>
  	<script>
  	var map;
  	function initMap(){
  		map = new google.maps.Map(document.getElementById('map'),{
        zoom: 2,
  			center: new google.maps.LatLng(2.8, -187.3),
        mapTypeId: 'terrain'
  		});

      var script = document.createElement('script');
      script.src = 'https://developers.google.com/maps/documentation/javascript/examples/json/earthquake_GeoJSONP.js';
        document.getElementsByTagName('head')[0].appendChild(script);
      }

      window.eqfeed_callback = function(results) {
        for (var i = 0; i < results.features.length; i++) {
          var coords = results.features&#91;i&#93;.geometry.coordinates;
          var latLng = new google.maps.LatLng(coords&#91;1&#93;,coords&#91;0&#93;);
          var marker = new google.maps.Marker({
            position: latLng,
            map: map
          });
        }
      }
    </script>
  	<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=notwatchk&callback=initMap">
</script>
</body>
</html>

住所からGoogle mapに2つのラベルを表示する

なんとなく、それらしいものができてきました。中心のポジションは、緯度経度の平均を取ってます。
あ、array_sum, countでできますね。
$lat_a = array_sum($lat)/count($lat);
$lng_a = array_sum($lng)/count($lng);

<?php

$resutaurant = array(
    "Brasserie de L'institut" => "東京都新宿区市谷船河原町15",
    "Le Mange-Tout" => '東京都新宿区納戸町22'
  );
function urlencode_rfc3986($str){
  return str_replace('%7E','~', rawurlencode($str));
}
$i = 0;
foreach($resutaurant as $name => $address){
  $encode_address = urlencode_rfc3986($address);

  $url = 'http://maps.google.com/maps/api/geocode/json?address='. $encode_address.'&sensor=false';
  $json = file_get_contents($url);
  $obj = json_decode($json,true);

  $lat[] = $obj["results"]["0"]["geometry"]["location"]["lat"];
  $lng[] = $obj["results"]["0"]["geometry"]["location"]["lng"];
  echo $name ." ".$address .'<br>';
  echo $lat[$i] ." " .$lng[$i]. "<br>";
  $rname[] = $name;
  $i++;
}

$lat_a = ($lat[0]+$lat[1])/2;
$lng_a = ($lng[0]+$lng[1])/2;


?>
<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      #map {
        height: 50%;
        margin-top: 10px;
      }
      html, body {
        height: 100%;
        margin: 10px;
        padding: 0;
      }
    </style>
  </head>
  <body>
  	<div id="map"></div>
  	<script>
  	var map;
  	function initMap(){
      var position = {lat: <?php echo $lat_a; ?>, lng: <?php echo $lng_a; ?>};
  		map = new google.maps.Map(document.getElementById('map'),{
  			center: position,
  			zoom: 16
  		});

      var labels = ["<?php echo $rname&#91;0&#93;; ?>","<?php echo $rname&#91;1&#93;; ?>"];

      var markers = locations.map(function(location, i) {
          return new google.maps.Marker({
            position: location,
            label: labels[i]
          });
        });

      var markerCluster = new MarkerClusterer(map, markers,
            {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
      }

    var locations = [
    {lat: <?php echo $lat&#91;0&#93;; ?>, lng: <?php echo $lng&#91;0&#93;; ?>},
    {lat: <?php echo $lat&#91;1&#93;; ?>, lng: <?php echo $lng&#91;1&#93;; ?>}
    ]
  	</script>
    <script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js">
    </script>
  	<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=hogehogek&callback=initMap">
</script>
</body>
</html>

住所からlat, lngを抽出して地図を表示

飯田橋のBrasserie de L’institutを表示してみましょう。
住所は、東京都新宿区市谷船河原町15。
google map apiのjsonでlat, lngを取得します。

jsのマップを表すクラスはMap, centerとzoomは必須。
callbackで、apiを読み込んだ後のinitMap()実行を指定しています。

<?php

$name = "Brasserie de L'institut";
$address = '東京都新宿区市谷船河原町15';
function urlencode_rfc3986($str){
  return str_replace('%7E','~', rawurlencode($str));
}
$encode_address = urlencode_rfc3986($address);

$url = 'http://maps.google.com/maps/api/geocode/json?address='. $encode_address.'&sensor=false';
$json = file_get_contents($url);
$obj = json_decode($json,true);

$lat = $obj&#91;"results"&#93;&#91;"0"&#93;&#91;"geometry"&#93;&#91;"location"&#93;&#91;"lat"&#93;;
$lng = $obj&#91;"results"&#93;&#91;"0"&#93;&#91;"geometry"&#93;&#91;"location"&#93;&#91;"lng"&#93;;
echo $name ." ".$address .'<br>';
echo $lat ." " .$lng;

?>
<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      #map {
        height: 50%;
        margin-top: 10px;
      }
      html, body {
        height: 100%;
        margin: 10px;
        padding: 0;
      }
    </style>
  </head>
  <body>
  	<div id="map"></div>
  	<script>
  	var map;
  	function initMap(){
  		map = new google.maps.Map(document.getElementById('map'),{
  			center:{lat: <?php echo $lat; ?>, lng: <?php echo $lng; ?>},
  			zoom: 16
  		});
  	}
  	</script>
  	<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=hogehoge&callback=initMap">
</script>
</body>
</html>

var markerを追加して、ラベルを付与できる。

   var map;
  	function initMap(){
      var position = {lat: <?php echo $lat; ?>, lng: <?php echo $lng; ?>};
  		map = new google.maps.Map(document.getElementById('map'),{
  			center: position,
  			zoom: 16
  		});
      var marker = new google.maps.Marker({
        position: position,
        map: map
      });
  	}

Javascriptの多次元配列

簡単ですね。

<script type="text/javascript">
var array =  { name: 'ジャパンリアルエステイト投資法人'};
console.log( array.name );

var reit =  { name: 'ジャパンリアルエステイト投資法人',
				price: '552,000',
				rate: 3.28
				};
console.log(reit.price)

var reit =  { name: 'ジャパンリアルエステイト投資法人',
				price: {
					investment: 578000,
					NAV: 501776
				}
			};
console.log(reit.price.NAV)
</script>

google map api

すご

<!DOCTYPE html>
<head>
	<meta name="viewport" content="initial-scale=1.0, user-scalable=no" >
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<title>Using Google Maps</title>
	<style>
	#map {
		height: 100%;
	}
	html, body {
		height: 100%;
		margin: 0;
		padding: 0;
	}
	</style>
</head>
<body>
	<div id="map"></div>

	<script>
		var customLabel = {
			restaurant: {
				label: 'R'
			},
			bar: {
				label: 'B'
			}
		};

		function initMap(){
			var map = new google.maps.Map(document.getElementById('map'),{
				center: new google.maps.LatLng(-33.863276, 151.207977),
				zoom: 12
			});
			var infoWindow = new google.maps.InfoWindow;

			downloadUrl('mapmaker.php', function(data){
				var xml = data.responseXML;
				var markers = xml.documentElement.getElementsByTagName('marker');
				Array.prototype.forEach.call(markers, function(markerElem){
					var name = markerElem.getAttribute('name');
					var address = markerElem.getAttribute('address');
					var type = markerElem.getAttribute('type');
					var point = new google.maps.LatLng(
						parseFloat(markerElem.getAttribute('lat')),
						parseFloat(markerElem.getAttribute('lng')));

					var infowincontent = document.createElement('div');
					var strong = document.createElement('strong');
					strong.textContent = name
					infowincontent.appendChild(strong);
					infowincontent.appendChild(document.createElement('br'));

					var text = document.createElement('text');
					text.textContent = address
					infowincontent.appendChild(text);
					var icon = customLabel[type] || {};
					var marker = new google.maps.Marker({
						map: map,
						position: point,
						label: icon.label
					});
					marker.addListener('click', function(){
						infoWindow.setContent(infowincontent);
						infoWindow.open(map, marker);
					});
				});
			});
		}

function downloadUrl(url, callback){
	var request = window.ActiveXObject ?
		new ActiveXObject('Microsoft.XMLHTTP') :
		new XMLHttpRequest;

	request.onreadystatechange = function(){
		if (request.readyState == 4){
			request.onreadystatechange = doNothing;
			callback(request, request.status);
		}
	};

	request.open('GET', url, true);
	request.send(null);
}

function doNothing(){}
</script>
<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=hogehoge&callback=initMap">
</script>
</body>
</html>

php5以上でCall to undefined function domxml_new_doc()

domxml_new_docがundefinedと出てしまった。

[vagrant@localhost map]$ php -v
PHP 5.6.27 (cli) (built: Oct 14 2016 14:06:54)

phpのversionは、5.6

php4.0からサポートされているのに何で?と思ったが、以下のようにphp5以上はDOM extensionを使えとのこと。
It will, however, never be released with PHP 5, and will only be distributed with PHP 4. If you need DOM XML support with PHP 5 you can use the DOM extension. This domxml extension is not compatible with the DOM extension.

こちらのDom Object Model
http://us3.php.net/manual/ja/book.dom.php

new DOMDocument(), createElement, appendChild, setAttribute, saveXMLに修正したら問題なく表示されました。

<?php
require("phpsqlajax_dbinfo.php");

$doc = new DOMDocument("1.0");

$node = $doc->createElement("makers");
$parnode = $doc->appendChild($node);

$connection =mysql_connect('localhost', $username, $password);
if (!$connection){
	die('Not connected : ' . mysql_error());
}

$db_selected = mysql_select_db($database, $connection);
if (!$db_selected){
	die ('Can\'t use db:' . mysql_error());
}

$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if(!$result){
	die('Invalid query:' . mysql_error());
}

header("Content-type: text/xml");

while ($row = @mysql_fetch_assoc($result)){
	$node = $doc->createElement("marker");
	$newnode = $parnode->appendChild($node);
	$newnode->setAttribute("name", $row['address']);
	$newnode->setAttribute("lat", $row['lat']);
	$newnode->setAttribute("lng", $row['lng']);
	$newnode->setAttribute("type", $row['type']);
}

$xmlfile = $doc->saveXML();
echo $xmlfile;
?>
<makers>
<marker name="580 Darling Street, Rozelle, NSW" lat="-33.861034" lng="151.171936" type="restaurant"/>
<marker name="76 Wilford Street, Newtown, NSW" lat="-33.898113" lng="151.174469" type="bar"/>
<marker name="Greenwood Plaza, 36 Blue St, North Sydney NSW" lat="-33.840282" lng="151.207474" type="bar"/>
<marker name="7A, 2 Huntley Street, Alexandria, NSW" lat="-33.910751" lng="151.194168" type="bar"/>
<marker name="16 Foster Street, Surry Hills, NSW" lat="-33.879917" lng="151.210449" type="bar"/>
<marker name="43 Macpherson Street, Bronte, NSW" lat="-33.906357" lng="151.263763" type="restaurant"/>
<marker name="60-64 Reservoir Street, Surry Hills, NSW" lat="-33.881123" lng="151.209656" type="restaurant"/>
<marker name="60 Riley Street, Darlinghurst, NSW" lat="-33.874737" lng="151.215530" type="restaurant"/>
</makers>

地図データを入れる

CREATE TABLE google.markers (
	id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	name VARCHAR(60) NOT NULL,
	address VARCHAR(80) NOT NULL,
	lat FLOAT(10, 6) NOT NULL,
	lng FLOAT(10, 6) NOT NULL,
	type VARCHAR(30) NOT NULL
) ENGINE = MYISAM;

INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Love.Fish', '580 Darling Street, Rozelle, NSW', '-33.861034', '151.171936', 'restaurant');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Young Henrys', '76 Wilford Street, Newtown, NSW', '-33.898113', '151.174469', 'bar');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Hunter Gatherer', 'Greenwood Plaza, 36 Blue St, North Sydney NSW', '-33.840282', '151.207474', 'bar');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('The Potting Shed', '7A, 2 Huntley Street, Alexandria, NSW', '-33.910751', '151.194168', 'bar');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Nomad', '16 Foster Street, Surry Hills, NSW', '-33.879917', '151.210449', 'bar');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Three Blue Ducks', '43 Macpherson Street, Bronte, NSW', '-33.906357', '151.263763', 'restaurant');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Single Origin Roasters', '60-64 Reservoir Street, Surry Hills, NSW', '-33.881123', '151.209656', 'restaurant');
INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Red Lantern', '60 Riley Street, Darlinghurst, NSW', '-33.874737', '151.215530', 'restaurant');

where 1 は無条件で全データを抽出という意味。

mysql> select * from markers where 1;
+—-+————————+———————————————–+————+————+————+
| id | name | address | lat | lng | type |
+—-+————————+———————————————–+————+————+————+
| 1 | Love.Fish | 580 Darling Street, Rozelle, NSW | -33.861034 | 151.171936 | restaurant |
| 2 | Young Henrys | 76 Wilford Street, Newtown, NSW | -33.898113 | 151.174469 | bar |
| 3 | Hunter Gatherer | Greenwood Plaza, 36 Blue St, North Sydney NSW | -33.840282 | 151.207474 | bar |
| 4 | The Potting Shed | 7A, 2 Huntley Street, Alexandria, NSW | -33.910751 | 151.194168 | bar |
| 5 | Nomad | 16 Foster Street, Surry Hills, NSW | -33.879917 | 151.210449 | bar |
| 6 | Three Blue Ducks | 43 Macpherson Street, Bronte, NSW | -33.906357 | 151.263763 | restaurant |
| 7 | Single Origin Roasters | 60-64 Reservoir Street, Surry Hills, NSW | -33.881123 | 151.209656 | restaurant |
| 8 | Red Lantern | 60 Riley Street, Darlinghurst, NSW | -33.874737 | 151.215530 | restaurant |
+—-+————————+———————————————–+————+————+————+
8 rows in set (0.00 sec)