CSSでLeafletの画像マーカーの色を変える

Leafletでマーカーに画像ファイルを使ってる場合、同じ形のマーカーで動的に色を変えたい場合、以前は色を違えた別の画像ファイルを用意して、アイコンのURLをセットする方法を行ってましたが、色数が多くなったり中間色を使う場合、別のファイルを用意するのも大変なので何とかならないかと調べてましたところ、
CSSのhue-rotateで色相環の回転位置を使って同じ画像ファイルで色を変えることがわかり試してみました。

ここで教えていただきました。

 

 

 

 

 

< 使った画像 >

黄色


< コード例 >

CSS


  /* 色相環回転色 */
  .acmarker_aqua {
    filter: hue-rotate(150deg);   /* 黄色から150度 */
  }
  .acmarker_orange {
    filter: hue-rotate(-45deg);   /* 黄色から-45度 */
  }
  .acmarker_aquamarine {
    filter: hue-rotate(120deg);   /* 黄色から120度 */
  }
  
  .acmarker_red {
    filter: hue-rotate(-90deg);   /* 黄色から-90度 */
  }
  .acmarker_fuchsia {
    filter: hue-rotate(-135deg);  /* 黄色から-135度 */ 
  }
  .acmarker_yellow {
    filter: hue-rotate(0deg);   
  }
  .acmarker_lightgreen {
    filter: hue-rotate(45deg);   /* 黄色から-45度 */ 
  }
  .acmarker_blue {
    filter: hue-rotate(150deg);  /* 黄色から-150度 */ 
  }
  
  .acmarker_blue_red {
    filter: hue-rotate(150deg);   /* 青から150度 */ 
  }
  
  .acmarker_blue_green {
    filter: hue-rotate(250deg);   /* 青から250度 */ 
  }

javaScript


      // 色相環回転色適用CSSクラス //
      let markerClass = isAquaChange ? "acmarker_aqua" : ""

      if (!isByAltMarker) {
        markerClass = isOrangeChange ? "acmarker_orange" : markerClass
        markerClass = isAquaMarineChange ? "acmarker_aquamarine" : markerClass
        markerClass = isPinkChange ? "acmarker_red" : markerClass
        markerClass = isRedChange ? "acmarker_blue_red" : markerClass
        markerClass = isGreenChange ? "acmarker_blue_green" : markerClass
      }

      // 高度別マーカーの場合 //
      if (isByAltMarker) {

        // 色名ディレクトリ、クラス名取得 //
        const altclass = new Altitude()
        const map = altclass.getIconColorDirClassName(lineitm.altidx)

        const coldir = map["dir"]
        const iconfnm = ICON_URL_OTHEROPE.split("/")[3]
        ICON_URL_OTHEROPE = `Img/apbytype/${coldir}/${iconfnm}`
        markerClass = map["class"]

        // Img/acbytype/yellow/ac_787.png
      }

      // 対象オペレータ飛行中 //
      const acicon = L.icon({
        iconUrl: ICON_URL,
        iconRetinaUrl: ICON_URL,
        iconSize: [szInt, szInt],
        iconAnchor: [szIntHalf, szInt],
        popupAnchor: [0, ppAnchorY],

        className: markerClass
      })
      // 他オペレータ飛行中 //
      const acicon_other = L.icon({
        iconUrl: ICON_URL_OTHEROPE,
        iconRetinaUrl: ICON_URL,
        iconSize: [szInt, szInt],
        iconAnchor: [szIntHalf, szInt],
        popupAnchor: [0, ppAnchorY],

        className: markerClass
      })

JavaScript 画像ディレクトリ、クラス名関数


  /**
   * 高度レベル別飛行機マーカーディレクトリ名クラス名
   * @param {type} level 高度レベル
   * @returns {Altitude.getIconColorDirClassName.map}
   */
  getIconColorDirClassName(level) {

    let map = {"dir": "white", "class": ""}


    if (level === 0) {
      map = {"dir": "blue", "class": "acmarker_blue_green"}
    }
    else if (level === 1) {
      map = {"dir": "blue", "class": "acmarker_blue_red"}
    }
    else if (level === 2) {
      map = {"dir": "fuchsia", "class": ""}  // Fucisia
    }
    else if (level === 3) {
      map = {"dir": "yellow", "class": ""}    // Yellow
    }
    else if (level === 4) {
      map = {"dir": "lightgreen", "class": ""}     // LightGreen
    }
    else if (level === 5) {
      map = {"dir": "blue", "class": ""}     // Blue
    }
    else if (level === 6) {
      map = {"dir": "yellow", "class": "acmarker_aqua"}    // Aqua
    }
    else if (level === 7) {
      map = {"dir": "white", "class": ""}     // white
    }

    return map
  }

< 画面例 >

3AFB Aviaton

飛行機の高度でアイコンの色を変えています。

画像ファイルにない色を使う。

GCP Translation API RESTでPHPから使う

< コード例 >


<?php

/*
  Google Translationリクエスト用スクリプト
  ソース言語は英語に固定
  
 */

include '../DefaultHeaderIni.php';
include '../MySQLConnectConfig_aviation.php';

// ============= Const =============== //

$URL = "https://www.googleapis.com/language/translate/v2?key=";
$KEY = "??????????????????????????????????";


// =================================== //

// == リクエストパラメータ取得 == //
$q = $_POST["q"] ? $_POST["q"] : $_GET["q"];
$target = $_POST["target"] ? $_POST["target"] : $_GET["target"];

if (!$q) {
  $q = "Good Morning";
}
if (!$target) {
  $target = "in";
}


// 送信データ //
// リテラルは必ずはシングルクオテーションにする //
$postdata = array(
    'q' => $q,
    'source' => 'en',
    'target' => $target
);

$postdata_json = json_encode($postdata);
$postdata_json = str_replace("\r", "", $postdata_json);
//exit;

$url = $URL.$KEY;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => $postdata_json,
    CURLOPT_HTTPHEADER => [
          'Content-Type: application/json; charset=UTF-8',
          "accept: application/json"
      ],
    
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
}
else {
  echo $response;
}

< リクエストForm data >

q: U A881 United Airlines B789 N17963 Landed 
from ORD to HND  Last Direction 269 Runway 22 Squawk 3126
21Seconds ago
target: ja

< レスポンス例 >

{
  "data": {
    "translations": [
      {
        "translatedText": "U A881 ユナイテッド航空 B789 N17963 ORD から HND に着陸 最後の方向 269 滑走路 22 スコーク 3126 21 秒前"
      }
    ]
  }
}

Leaflet Javascript 地図内に画像を配置

HTMLで地図を配置したdiv内に画像用divを配置して、CSSで画像用divの位置をセットします。

< コード例 >
HTML
#livemap_photoのsrcはJavascriptでダイナミカリーにセットしています。

<!-- Leaflet伸縮地図 -->
<div id="livemap-container" class="z-depth-1-half map-container p-0">
<!-- 省略 -->
<!-- Planespotter 機材写真 -->
    <figure>
        <div id="livemap_photo_div" class="dsp_none">
            <a id="livemap_photo_a" href="" target="_blank">
                <img id="livemap_photo" src="" width="240" class="border border-primary rounded fade-in"></img>
            </a>
            <figcaption id="livemap_photo_figcap" class="flagcap_dark">..</figcaption>

        </div>
    </figure>
</div>

CSS

positionを absoluteにする
bootom, top, left. right で地図内でのパッディングをセットする
z-indexを地図より大きくする

/* ライブ地図機材写真 */
#livemap_photo_div {
    position: absolute;
    bottom: 8px;
    left: 8px;
    z-index: 99999;
    color: white;
    font-size: 14px;
    opacity: 0.8
}

< 画面例 >

Planespotters PHOTO API

飛行機の機材番号からその飛行機の写真を取得するため、以前はGoogleのSerach APIを使ってましたが、マイナーな航空会社の場合、はずれが多く課金もされので、ふさわしいのを探してましたところ、見つけました。

Home : https://www.planespotters.net/
API DOCUMENT : https://www.planespotters.net/photo/api

< 特長 >

1) アカウントキーなしで使えます。
2) 最新の1枚の情報が取得出来ます。
3) サムネイルのサイズは2種類
4) 写真の保存は禁止
5) 応答結果の保存は24時間以内

< Terms of use >

The use of photos in your website or application cannot be an exclusive paid, premium or member-only feature. Each area that will include photos must be publicly and freely available to all users. Thumbnail sizes used in your website or application must be the same across all access levels.
Each photo must be attributed to the photographer and the thumbnail linked back to the original page at Planespotters.net in accordance with our general Terms of Use.
API responses must not be stored for more than 24 hours.
All URLs, including image sources and links to photos, must remain unchanged and as provided in the API response.
Image files must not be stored on your servers or inside your application and must be served from the original URL provided in the API response.

< 利用規約 >

ウェブサイトまたはアプリケーションでの写真の使用は、有料、プレミアム、またはメンバー限定の機能であってはなりません。 写真を含む各領域は、公開され、すべてのユーザーが自由に利用できる必要があります。 Web サイトまたはアプリケーションで使用されるサムネイルのサイズは、すべてのアクセス レベルで同じでなければなりません。
各写真は写真家に帰属し、サムネイルは一般的な利用規約に従って Planespotters.net の元のページにリンクされている必要があります。
API 応答は 24 時間以上保存しないでください。
画像ソースや写真へのリンクを含むすべての URL は変更せず、API 応答で提供されているとおりにする必要があります。
画像ファイルは、サーバー上またはアプリケーション内に保存してはならず、API 応答で提供された元の URL から提供する必要があります。

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

航空情報 2023年 3月号 [雑誌]
価格:1425円(税込、送料無料) (2023/2/9時点)

GoogleMap Javascript のツールチップ

Leaflet Javascriptのツールチップがいい感じに出来たので、グレートサークルラインがかんたんなので、GoogleMapを使ってるアプリで同じようなこと出来ないか調べてみたところ、
Google語では、Labelのようで、調べて実装してみました。

ここで教えて頂きました。

公式ドキュメント(英語)

公式ドキュメント(日本語)

< コード例 >
マーカーのプロパティに label をセットします。


// 空港IATAラベル //
    let label = new google.maps.Marker({
      position: latlng,
      map: this.map,
      icon: {
        url: '',
        size: new google.maps.Size(1, 1),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(0, -12), // //左に0px、下に12px テキストはセンター
      },
      label: {
        text: this.poptxt,
        color: '#ffff00',
        fontFamily: 'sans-serif',
        fontWeight: 'bold',
        fontSize: '14px'
      }
    });

// 中央上ラベル //
          DrawMapG.nclabel = new google.maps.Marker({
            position: nclatlng,
            map: mapThis,
            icon: {
              url: '',
              size: new google.maps.Size(1, 1),
              origin: new google.maps.Point(0, 0),
              anchor: new google.maps.Point(0, -12), // //左に0px、下に12px テキストはセンター
            },
            label: {
              text: this.nctxt,
              color: '#ffffff',
              fontFamily: 'sans-serif',
              fontWeight: 'bold',
              fontSize: '14px'
            }
          });

         // 中央下ラベル //
          DrawMapG.sclabel = new google.maps.Marker({
            position: sclatlng,
            map: mapThis,
            icon: {
              url: '',
              size: new google.maps.Size(1, 1),
              origin: new google.maps.Point(0, 0),
              anchor: new google.maps.Point(0, 30), // //右に0px、上に30px テキストはセンター
            },
            label: {
              text: this.sctxt,
              color: '#ffffff',
              fontFamily: 'sans-serif',
              fontWeight: 'bold',
              fontSize: '14px'
            }
          });
 

< 画面例 >

AirLabs Data API Real Flights

OpenSky のフリーのフライトライブのAPIが2022年5月頃から利用制限がかかるようになり日次で超過すると使えなくなり、他を探していたところ AirLabsのFlight Tracker Real Flightsで同じことができるので使ってます。

AirLabs Home

OpenSkyのフライトライブになかった、フライト番号、出発空港、到着空港なんかも入っていてFlightRadarのデータに近く便利ですが、更新インターバルがやや長く、20秒間隔くらいでアップデートされています。
リクエストパラメーターにバウンズの他、エアライン、空港が使えます。

Flight Tracker API

< リクエストパラメーター >

< 応答例 >

 

 

 

 

 

 

 

 

 

 

 

 

 

< 利用例 >
羽田到着機でフィルター

ANAでフィルター

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

航空情報 2023年 3月号 [雑誌]
価格:1425円(税込、送料無料) (2023/2/9時点)

楽天で購入

 

 

 

IATA and ICAO Codes

Androidアプリで航空会社マスタを起動時に読込、スタティックで保存するために使ってます。
人気度低いですが、正常稼働率100%で、プランはありません。無償で利用出来ます。

ドキュメント : https://api.rakuten.net/vacationist/api/iata-and-icao-codes

< コード例 Java OKHttp >


OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
	.url("https://iatacodes-iatacodes-v1.p.rapidapi.com/api/v9/flights?bbox=46.01%2C-12.21%2C56.84%2C9.66")
	.get()
	.addHeader("x-rapidapi-key", "????????????????????????????")
	.addHeader("x-rapidapi-host", "iatacodes-iatacodes-v1.p.rapidapi.com")
	.build();

Response response = client.newCall(request).execute();

< レスポンス例 >

パラメータなしでリクエストして、756件の応答がありました。

OpenSky REST API

FlightRadarやFlightAwareにあるような飛行機のライブマップを作ることになり、無償または安価なAPIをさがしてましたところ見つけましたので使ってます。

ドキュメントURL : https://opensky-network.org/apidoc/rest.html

個人利用、非営利目的利用は自由ですが、広告掲載には同意が必要です。

関連FAQリンク : https://opensky-network.org/about/faq#q6

Androidアプリで広告入れて使いたいので、質問したところ、OKの回答をいただいてます。
PlayStoreリンク

[ メリット ]
1) 無償で使える
2) ライブマップはほぼリアルタイム
3) ライブマップの範囲を四角いバウンダリで指定できるので地図に最適(他で見つけたのが半径なので、面倒なのでやめる)
4) ライブマップは範囲指定の他、ICAO24指定で単機のステータスもわかる

[ デメリット ]
1) レスポンス時間が長い場合があり、タイムアウトも多い
2) 研究目的なデータなので、フライトナンバー、ルートはわからない
3) 過去データの航跡追跡は現在休止中
4) カバー出来てない地域(上海北京周辺、北北海道、アフリカ)、飛行中機がまばらな地域(東南アジア)がある
5) 各飛行機のADS-Bの運用上の問題かも知れないが、着陸前空中にいる状況で途切れ、アプローチ中消えてる場合が多い

2022年4月から1日あたりの利用数制限が行われています。1日200回程度までの取得後ブロックされます。