Google mapsに天気アイコンをつけてみる

Livedoor Weather Hacksを使って何をしようか考えましたが、真っ先に思いついたのがGoogle mapsの地図に貼り付けてみることでした。 ということで、やってみました。

実は結構大変だった

最初は「GXmlHttpを使ってRSS情報をそのまま読んで解析すればいいや〜」と軽く考えていましたが、実は結構大変でした。 というのも、GXmlHttpはGoogle maps api用スクリプトが置いてある場所以外からはXMLを取って来れないからです。 これはセキュリティ上の制限で、Google maps apiが悪いというよりも、下位にあるJavascriptの制限でした。

でも、やっぱりGoogle mapsに表示したかったのでかなり強引な方法を使いました。 自サイトにLivedoor Weather Hacks専用転送スクリプトを書いて無理やり同一サイトからRSSを取っている形にしてしまいました。

サンプル

札幌の明日の天気を表示してみました。 出力結果はこんな感じです。 firefoxとIEで試しました。

ソースコード(google maps api)


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script src="http://maps.google.com/maps?file=api&v=1&key=YOUR_GOOGLE_MAPS_KEY"
        type="text/javascript" charset="UTF-8"></script>
    <script type="text/javascript">
    //<![CDATA[

    var map;

    function onLoad() {
      map = new GMap(document.getElementById("map"));

      var point = new GPoint(141.36, 43.05);

      map.centerAndZoom(point, 11);
      map.setMapType(G_SATELLITE_TYPE);

      var request = GXmlHttp.create();

      // use custom mirror since GXmlHttp can only get
      // data from the same host.
      // (there might be a better way...)
      request.open("GET", "./mirror-weatherhacks.php", true);

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          var rssitem = request.responseXML.getElementsByTagName("item");

          for (var i=0; i < rssitem.length; i++) {
            var cat = rssitem[i].getElementsByTagName("category");
            if (cat[0].childNodes[0].nodeValue == "PR") {
              // skip ad
              continue;
            }

            // get url of OTENKI icon
            var urlobj = rssitem[i].getElementsByTagName("url");
            var url = urlobj[0].childNodes[0].nodeValue;

            // get width of OTENKI icon
            var widthobj = rssitem[i].getElementsByTagName("width");
            var width = widthobj[0].childNodes[0].nodeValue;

            // get height of OTENKI icon
            var heightobj = rssitem[i].getElementsByTagName("height");
            var height = heightobj[0].childNodes[0].nodeValue;

            // create a marker with OTENKI icon
            var icon = new GIcon();
            icon.image = url;
            icon.iconSize = new GSize(width, height);
            icon.iconAnchor = new GPoint(0, 0);

            var marker = new GMarker(point, icon);
            map.addOverlay(marker);

            break;
          }
        }
      }
      request.send(null);
    }

    //]]>
    </script>
  </head>
  <body onload="onLoad()" style="margin:0px; padding:0px;">
    <div id="map" style="width:450px; height:400px; padding:0px; margin:0px;"></div>
  </body>
</html>

ソースコード(RSS転送)

mirror-weatherhacks.phpというファイル名で使いました。


<?php

$host = "weather.livedoor.com";
$path = "/forecast/rss/1b/4.xml";
$content_type = "";

$fp = fsockopen($host, 80, $errno, $errstr, 30);

if (!$fp) {
  echo "<ERROR>$errstr ($errno)</ERROR>";
} else {
  $httpreq = "GET $path HTTP/1.0\r\n";
  $httpreq .= "Connection: Close\r\n";
  $httpreq .= "\r\n";

  fwrite($fp, $httpreq);

  # get http status line
  $statusline = fgets($fp, 2048);

  # get http header
  while (!feof($fp)) {
    $header = fgets($fp, 2048);
    if (strncasecmp($header, "Content-Type:", 13) == 0) {
      $content_type = $header;
    } else if ($header == "\r\n" || $header == "\r" || $header == "\n") {
      break;
    }
  }

  $content = "";
  while (!feof($fp)) {
    $content .= fgets($fp, 8196);
  }

  fclose($fp);

  if ($content_type != "") {
    header($content_type);
  }

  echo $content;
}

?>


IPv6基礎検定

YouTubeチャンネルやってます!