Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@takaakiyayoi

Google Maps Static APIでサイズの異なるカスタムアイコンを配置する

More than 1 year has passed since last update.

動機付け

こちらのサイトを作りました。コロナウイルスに関する呟きを集計、可視化します。
corona-virus-trend - コロナウイルス情報を分析・可視化

呟かれている地名の頻度に応じて地図上にマッピングしたいと思ったのがきっかけです。
地図

前提条件

  • GCPでAPIキーを取得します。
  • サーバサイドスクリプト(PHP)が稼働するサーバを持っている必要があります。

ドキュメント

こちらに書いてあることがほぼ全てですが、いくつか詰まったところもありました。
Developer Guide  |  Maps Static API  |  Google Developers

カスタムアイコンのサイズ変更

サーバ上に画像を準備して以下の書式に合わせてURLを組み立てればいいのですが、自分はこのアイコンのサイズを地名のキーワードの頻度に合わせて変化させたかったのです。
markers=icon:URLofIcon|markerLocation

それぞれのサイズの画像を準備するという手もありますが、自分は動的にアイコンのサイズを変えることにしました。PHPを使っているのでこちらを参考にさせていただきました。ブラウザに直接出力しています。marker.pngは元画像、適宜パスを変えてください。
PHP: GDで画像のサイズ変更やサムネイル生成のやりかた - Qiita

resize.php
<?php
header('Content-Type: image/png');

/**
 * 画像のサイズを変形して保存する
 * @param string $srcPath
 * @param int $width
 * @param int $height
 */
function transform_image_size($srcPath, $width, $height)
{
    list($originalWidth, $originalHeight, $type) = getimagesize($srcPath);
    switch ($type) {
        case IMAGETYPE_JPEG:
            $source = imagecreatefromjpeg($srcPath);
            break;
        case IMAGETYPE_PNG:
            $source = imagecreatefrompng($srcPath);
            break;
        case IMAGETYPE_GIF:
            $source = imagecreatefromgif($srcPath);
            break;
        default:
            throw new RuntimeException("サポートしていない画像形式です: $type");
    }

    $canvas = imagecreatetruecolor($width, $height);
    //ブレンドモードを無効にする
    imagealphablending($canvas, false);
    //完全なアルファチャネル情報を保存するフラグをonにする
    imagesavealpha($canvas, true);

    imagecopyresampled($canvas, $source, 0, 0, 0, 0, $width, $height, $originalWidth, $originalHeight);

    imagepng($canvas, null);

    imagedestroy($source);
    imagedestroy($canvas);
}

$size = $_GET['size'];
transform_image_size('marker.png', $size, $size);
?>

カスタムアイコンの呼び出し数制限

呼び出すときに、時々カスタムアイコンではなくデフォルトアイコンになってどうしてだろうと数日悩みました。結局最初のドキュメントをチキンと読んでおくべきだったということです。一度の呼び出しで5種類までのカスタムアイコンしか呼べないということです。
Google Maps Static Map - Custom icons limit - Stack Overflow

Static Maps service allows up to five unique custom icons per request.
Note that each of these unique icons may be used multiple times within the static map.

ということで、アイコンの種類数を5種類に限定するロジックを組み込みました。最大値、最小値を取得してからその間の区間を3等分。以下のコードでは、$itemsに地名と頻度が格納されていて、Geocodingしてから地図を呼び出しています。

static_map.php
<?php
// put the data in the array
$data_arr = array();

foreach ($items as $address => $value) {
  // url encode the address
  $address = urlencode($address);

  // google map geocode api url
  $url = "https://maps.googleapis.com/maps/api/geocode/json?address={$address}&key=APIKEY";

  // get the json response
  $resp_json = file_get_contents($url);

  // decode the json
  $resp = json_decode($resp_json, true);

  // response status will be 'OK', if able to geocode given address 
    if($resp['status']=='OK'){

        // get the important data
        $lat = isset($resp['results'][0]['geometry']['location']['lat']) ? $resp['results'][0]['geometry']['location']['lat'] : "";
        $long = isset($resp['results'][0]['geometry']['location']['lng']) ? $resp['results'][0]['geometry']['location']['lng'] : "";
        $formatted_address = isset($resp['results'][0]['formatted_address']) ? $resp['results'][0]['formatted_address'] : "";

        // verify if data is complete
        if($lat && $long && $formatted_address){

            array_push(
                $data_arr, 
                    array($lat, 
                    $long, 
                    $formatted_address,
                    $value)
                );

       }
    }
}

// size mapping
$min = $data_arr[0][3];
$max = $data_arr[0][3];
foreach ($data_arr as $item) {
  if($min > $item[3] ) $min = $item[3];
  if($min < $item[3] ) $max = $item[3];
}

$range = $max - $min;
$portion = $range / 3;

// url building
$base_url = 'https://maps.googleapis.com/maps/api/staticmap?size=640x640&language=ja&maptype=roadmap&key=APIKEY';

$marker_array = array();
foreach ($data_arr as $item) {

  if($item[3] == $min)
    $size = $min;
  else if($item[3] > $min && $item[3] <= $min + $portion)
    $size = $min + $portion;
  else if($item[3] > $min + $portion && $item[3] <= $min + $portion * 2)
    $size = $min + $portion * 2;
  else if($item[3] > $min + $portion * 2 && $item[3] <= $min + $portion * 3)
    $size = $min + $portion * 3;
  else if($item[3] == $max)
    $size = $max;

  $marker_url = urldecode("http://corona-virus-trend.com/xxx/resize_icon.php?size={$size}");
  $marker_para = "markers=anchor:center|icon:{$marker_url}|{$item[2]}";
  array_push($marker_array, $marker_para);
}

$marker_para_str = join("&", $marker_array);
$map_url = $base_url . "&" . $marker_para_str;

print("<img src=\"$map_url\">");
?>

参考資料

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?