Leaflet Javascript ツールチップがポリラインに重ならないようにする

< コード例 >


  /**
   * チャートWaypointツールチップ位置、オフセット取得
   * 三角形にして頂点(カレント)への方向の領域を返す
   * 
   * @param {type} prev 前回データ
   * @param {type} curr 今回データ
   * @param {type} next 次回データ
   * @returns {StaticMap.getTooltipDirection.staticmapAnonym$9} Direction文字列、
   * オフセットxy配列
   */
  getTooltipDirectionByArrow(prev, curr, next) {

    const DIRECTIONS = ["top", "right", "bottom", "left"]
    const OFFSETS = [[0, -10], [10, 0], [[0, 10]], [-10, 0]]

    const pll = [prev["LON"], prev["LAT"]]
    const cll = [curr["LON"], curr["LAT"]]
    const nll = [next["LON"], next["LAT"]]


    const tf = new MyTurf()

    let topdir = parseInt(tf.getBearing(cll, pll) + 45)
    let tondir = parseInt(tf.getBearing(cll, nll) + 45)
    topdir = topdir < 0 ? topdir + 360 : topdir
    tondir = tondir < 0 ? tondir + 360 : tondir
    const diffdir = Math.abs(topdir - tondir)

    // p -> c -> n が直線になってない場合 //
    if (diffdir > 190 && diffdir < 170) {
      // PとNの中間点 //
      const pnc = tf.midpoint(pll, nll)
      // PN中間点からのCへの方向 //
      let arrowdir = parseInt(tf.getBearing(pnc, cll) + 45)
      arrowdir = arrowdir < 0 ? arrowdir + 360 : arrowdir

      const arrowArea = Math.floor(arrowdir / 90)


      return {
        direction: DIRECTIONS[arrowArea],
        offset: OFFSETS[arrowArea]
      }
    }
    // 直線になってる場合、線なし領域最初を返す //
    else {
      return new StaticMap().getTooltipDirection(prev, curr, next)
    }

  }


  /**
   * チャートWaypointツールチップ位置、オフセット取得
   * 線が引かれてない領域を返す
   * 
   * @param {type} prev 前回データ
   * @param {type} curr 今回データ
   * @param {type} next 次回データ
   * @returns {StaticMap.getTooltipDirection.staticmapAnonym$9} Direction文字列、
   * オフセットxy配列
   */
  getTooltipDirection(prev, curr, next) {

    const AREAS = [0, 1, 2, 3]
    const DIRECTIONS = ["top", "right", "bottom", "left"]
    const OFFSETS = [[0, -10], [10, 0], [[0, 10]], [-10, 0]]

    const pll = [prev["LON"], prev["LAT"]]
    const cll = [curr["LON"], curr["LAT"]]
    const nll = [next["LON"], next["LAT"]]

    const tf = new MyTurf()
    let topdir = parseInt(tf.getBearing(cll, pll) + 45)
    let tondir = parseInt(tf.getBearing(cll, nll) + 45)
    topdir = topdir < 0 ? topdir + 360 : topdir
    tondir = tondir < 0 ? tondir + 360 : tondir


    const pavoidArea = Math.floor(topdir / 90)
    const navoidArea = Math.floor(tondir / 90)

    // 余った領域 //
    const putAreas = AREAS.filter(n => n !== pavoidArea && n !== navoidArea)

    return {
      //topdir: topdir,
      //tondir: tondir,
      //pavoidArea: pavoidArea,
      //navoidArea: navoidArea,
      //putAreas: putAreas,
      direction: DIRECTIONS[putAreas[0]],
      offset: OFFSETS[putAreas[0]]
    }

  }

Call


    const tff = new StaticMap()
    pdatas.forEach((p, i) => {
      plls.push([p["LAT"], p["LON"]])

      if (i > 0 && i < pdatas.length - 1) {
        //console.log("-- offset result " + p["IDENT"])

        // ツールチップ配置位置、オフセット //
        const ttpdir = tff.getTooltipDirectionByArrow(pdatas[i - 1], p, pdatas[i + 1])
        //console.log(ttpdir)
        ttpdirs.push(ttpdir["direction"])
        ttpoffsets.push(ttpdir["offset"])


      }
    })

< 画面例 >

Leaflet Javascript arrowheadプラグインで矢印をつける

飛行機の飛行経路チャートで方向がわかるようにするため矢印をつけるプラグインを探してたところ、ぴったりなのが見つかり早速使ってみました。

Leaflet ArrowHead

< コード例 >

HTML


<!-- Leaflet aroowhead -->
<script src="Script/js/leaflet-arrowheads.js"></script>
<script src="Script/js/leaflet.geometryutil.js"></script>

Javascript


 const ARROWHEADS_OPTIONS = {
      size: '12px',
      yawn: 50,
      fill: true,
      //frequency: 'endonly',
      frequency: '20000m',
      offsets: {end: '12px'}
    }

 this.lines = L.polyline(plls, POLYLINE_OPTIONS).arrowheads(ARROWHEADS_OPTIONS).addTo(this.smap)

< 画面例 >

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

航空情報 2023年 7月号 [雑誌]
価格:1,425円(税込、送料無料) (2023/5/24時点)

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

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

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

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
}

< 画面例 >

Leaflet Javascript のベースレイヤーでMapboxのレイヤーを使う

[ コード例 ]

レイヤー定義クラス



/**
 * Leaflet地図レイヤークラス
 * @type type
 */
class MapLayers {

  constructor() {
  }

  /**
   * 明暗種別取得
   * @param {type} label
   * @returns 
   */
  getLDType(label) {

    const mpl = new MapLayers();
    const ary = mpl.getLeafletBaseMapLayerArray();
    for (let j = 0; j < ary.length; j++) {
      if (label === ary[j]["label"]) {
        return ary[j]["ldtp"];
      }
    }

  }

  /**
   * ベースレイヤー
   * @returns {Array}
   */
  getLeafletBaseMapLayerArray() {
    const LEAFLET_LAYERS = [
      {
        label: '国土地理院標準',
        url: 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
        attr: {attribution: "地理院標準"},
        ldtp: "L"
      },
      {
        label: '国土地理院淡色',
        url: 'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
        attr: {attribution: "地理院淡色"},
        ldtp: "L"
      },
      {
        label: 'オープンストリートマップ',
        url: 'http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
        attr: {attribution: "OpenStreetMap contributors"},
        ldtp: "L"
      },
      {
        label: 'グーグル衛星',
        url: 'http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',
        attr: {
          maxZoom: 20,
          subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
        },
        ldtp: "D"
      },

      // 2021-04-11 //
      {
        label: 'USGS 衛星 Topo',
        url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: "Tiles courtesy of the U.S. Geological Survey"},
        ldtp: "D"
      },

      {
        label: 'Esri 衛星',
        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"},
        ldtp: "D"
      },

      {
        label: 'Stadia Maps Dark',
        url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png',
        attr: {
          attribution: "Stadia Maps"},
        ldtp: "D"
      },
      // 2021-04-11 終わり //

      // 2021-04-12 //
      {
        label: 'CartoDB DarkMatter',
        url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
        attr: {
          attribution:
                  '© OpenStreetMap contributors © CARTO'
        },
        ldtp: "D"
      },

      {
        label: '白地図',
        url: 'http://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png',
        attr: {id: 'blankmap', attribution: "地理院白地図"},
        ldtp: "L"
      },
      {
        label: 'Stamen Toner-Background',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'toner-background'
        },
        ldtp: "D"
      },

      {
        label: 'Stamen Toner-Lite',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'toner-lite'
        },
        ldtp: "L"
      },
      {
        label: 'Stamen Watercolor',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'watercolor'
        },
        ldtp: "L"
      },
      {
        label: 'Esri World Topo Map',
        url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: 'Tiles ©  Esri Japan '
        },
        ldtp: "L"
      },
      {
        label: 'Esri Ocean Base Map',
        url: 'http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}',
        attr: {
          maxZoom: 13,
          attribution: 'Tiles by  Esri Japan '
        },
        ldtp: "L"
      },
      
      // From mapbox //
      {
        label: 'Mapbox dark',
        url: 'https://api.mapbox.com/styles/v1/mapbox/dark-v9/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox satellite',
        url: 'https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox satellite streets',
        url: 'https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v11/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox night traffic',
        url: 'https://api.mapbox.com/styles/v1/mapbox/traffic-night-v2/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox day traffic',
        url: 'https://api.mapbox.com/styles/v1/mapbox/traffic-day-v2/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      {
        label: 'Mapbox outdoor',
        url: 'https://api.mapbox.com/styles/v1/mapbox/outdoors-v11/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      {
        label: 'Mapbox light',
        url: 'https://api.mapbox.com/styles/v1/mapbox/light-v10/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      /* {
        label: 'Mapbox decimal',
        url: 'https://api.mapbox.com/styles/hisashitanaka/ckj2fjsoj0alp19pqqtcvfk0i/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },*/
      
    ];
    return LEAFLET_LAYERS;
  }
  
  // mapboxgl.accessToken = "????";
  
  /**
   * OpenWeatherMap気象レイヤー Ver 1
   * @returns {Array}
   */
  getLeafletWeatherMapLayerArray() {

    const WEATHER_LAYERS = [
      {
        label: "Precipitation",
        url: 'http://{s}.tile.openweathermap.org/map/precipitation_new/{z}/{x}/{y}.png?appid=????',
        attr: {attribution: '降水',
          opacity: 0.9
        }
      },

      {
        label: "Clouds",
        url: 'http://{s}.tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=????',
        attr: {attribution: '',
          opacity: 0.9
        }
      },

      {
        label: "Pressure",
        url: 'http://{s}.tile.openweathermap.org/map/pressure_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気圧',
          opacity: 0.9
        }
      },

      {
        label: "Wind",
        url: 'http://{s}.tile.openweathermap.org/map/wind_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速',
          opacity: 0.9
        }
      },
      
      {
        label: "Temperture",
        url: 'http://{s}.tile.openweathermap.org/map/temp_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気温',
          opacity: 0.9
        }
      }
    ];
    return WEATHER_LAYERS;

  }
  
  /**
   * OpenWeatherMap気象レイヤー Ver 2
   * Freeライセンスでは利用不可
   * @returns {Array}
   */
  getLeafletWeatherMapLayerArrayV2() {

    const WEATHER_LAYERS = [
      {
        label: "Precipitation",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/TA2/{z}/{x}/{y}.png?appid=????&fill_bound=true',
        attr: {attribution: '降水',
          opacity: 0.9
        }
      },

      {
        label: "Clouds",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/CL/{z}/{x}/{y}.png?appid=????&fill_bound=true',
        attr: {attribution: '',
          opacity: 0.9
        }
      },

      {
        label: "Pressure",
        url: 'https://{s}.tile.openweathermap.org/map/pressure_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気圧',
          opacity: 0.9
        }
      },

      {
        label: "Wind",
        url: 'https://{s}.tile.openweathermap.org/map/wind_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速',
          opacity: 0.9
        }
      },
      
      {
        label: "Wind with direction",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/WND/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速風向',
          opacity: 0.9
        }
      },
      
      {
        label: "Temparture",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/TA2/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気温',
          opacity: 0.9
        }
      }
    ];


    return WEATHER_LAYERS;

  }

}

地図描画クラス

    // -- ベースレイヤー設定 -- //
    // -C
    const layersclass = new MapLayers();
    let leyers = layersclass.getLeafletBaseMapLayerArray();
    //alert(leyers.length);

    let baseMaps = {};
    let curkey = "";
    let objlayer;
    $.each(leyers, function (j, itm) {
      curkey = itm["label"];
      objlayer = L.tileLayer(itm["url"], itm["attr"]);
      baseMaps[curkey] = objlayer;

      //console.log("curkey:" + curkey);
      //console.log("LDTP:" + itm["ldtp"]);
    });

    // -- OpenWeatherMap設定 -- //
    // -C
    leyers = layersclass.getLeafletWeatherMapLayerArray();
    let weatherMaps = [];

    $.each(leyers, function (j, itm) {
      curkey = itm["label"];
      objlayer = L.tileLayer(itm["url"], itm["attr"]);
      weatherMaps[curkey] = objlayer;
    });


    // 天気選択を加えたレイヤーコントロール //
    L.control.layers(baseMaps, weatherMaps, /*{collapsed: false}*/).addTo(lmap);
    // ベースマップを乗せる //
    let baseadd = baseMaps[layerkey].addTo(lmap);

[ 画面例 ]

Mapbox Night Traffic

Leaflet Javascript に OpenWeatherMap の天気レイヤーを重ねる

ここで教えていただきました。
https://blog.kazu634.com/labs/leaflet-js-mapbox-js/001-leaflet-js-tutorial/

[ コード例 ]


   
/**
 * Leaflet地図レイヤークラス
 * @type type
 */
class MapLayers {

  constructor() {
  }

  /**
   * 明暗種別取得
   * @param {type} label
   * @returns 
   */
  getLDType(label) {

    const mpl = new MapLayers();
    const ary = mpl.getLeafletBaseMapLayerArray();
    for (let j = 0; j < ary.length; j++) {
      if (label === ary[j]["label"]) {
        return ary[j]["ldtp"];
      }
    }

  }

  /**
   * ベースレイヤー
   * @returns {Array}
   */
  getLeafletBaseMapLayerArray() {
    const LEAFLET_LAYERS = [
      {
        label: '国土地理院標準',
        url: 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
        attr: {attribution: "地理院標準"},
        ldtp: "L"
      },
      {
        label: '国土地理院淡色',
        url: 'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
        attr: {attribution: "地理院淡色"},
        ldtp: "L"
      },
      {
        label: 'オープンストリートマップ',
        url: 'http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
        attr: {attribution: "OpenStreetMap contributors"},
        ldtp: "L"
      },
      {
        label: 'グーグル衛星',
        url: 'http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',
        attr: {
          maxZoom: 20,
          subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
        },
        ldtp: "D"
      },

      // 2021-04-11 //
      {
        label: 'USGS 衛星 Topo',
        url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: "Tiles courtesy of the U.S. Geological Survey"},
        ldtp: "D"
      },

      {
        label: 'Esri 衛星',
        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"},
        ldtp: "D"
      },

      {
        label: 'Stadia Maps Dark',
        url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png',
        attr: {
          attribution: "Stadia Maps"},
        ldtp: "D"
      },
      // 2021-04-11 終わり //

      // 2021-04-12 //
      {
        label: 'CartoDB DarkMatter',
        url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
        attr: {
          attribution:
                  '© OpenStreetMap contributors © CARTO'
        },
        ldtp: "D"
      },

      {
        label: '白地図',
        url: 'http://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png',
        attr: {id: 'blankmap', attribution: "地理院白地図"},
        ldtp: "L"
      },
      {
        label: 'Stamen Toner-Background',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'toner-background'
        },
        ldtp: "D"
      },

      {
        label: 'Stamen Toner-Lite',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'toner-lite'
        },
        ldtp: "L"
      },
      {
        label: 'Stamen Watercolor',
        url: 'http://{s}.tile.stamen.com/{variant}/{z}/{x}/{y}.png',
        attr: {
          attribution: 'Map tiles by Stamen Design, ',
          variant: 'watercolor'
        },
        ldtp: "L"
      },
      {
        label: 'Esri World Topo Map',
        url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}',
        attr: {
          attribution: 'Tiles ©  Esri Japan '
        },
        ldtp: "L"
      },
      {
        label: 'Esri Ocean Base Map',
        url: 'http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}',
        attr: {
          maxZoom: 13,
          attribution: 'Tiles by  Esri Japan '
        },
        ldtp: "L"
      },
      
      // From mapbox //
      {
        label: 'Mapbox dark',
        url: 'https://api.mapbox.com/styles/v1/mapbox/dark-v9/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox satellite',
        url: 'https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox satellite streets',
        url: 'https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v11/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox night traffic',
        url: 'https://api.mapbox.com/styles/v1/mapbox/traffic-night-v2/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },
      {
        label: 'Mapbox day traffic',
        url: 'https://api.mapbox.com/styles/v1/mapbox/traffic-day-v2/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      {
        label: 'Mapbox outdoor',
        url: 'https://api.mapbox.com/styles/v1/mapbox/outdoors-v11/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      {
        label: 'Mapbox light',
        url: 'https://api.mapbox.com/styles/v1/mapbox/light-v10/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "L"
      },
      
      /* {
        label: 'Mapbox decimal',
        url: 'https://api.mapbox.com/styles/hisashitanaka/ckj2fjsoj0alp19pqqtcvfk0i/tiles/{z}/{x}/{y}?access_token=????',
        attr: {
          maxZoom: 13,
          attribution: 'mapbox'
        },
        ldtp: "D"
      },*/
      
    ];
    return LEAFLET_LAYERS;
  }
  
  // mapboxgl.accessToken = "????";
  
  /**
   * OpenWeatherMap気象レイヤー Ver 1
   * @returns {Array}
   */
  getLeafletWeatherMapLayerArray() {

    const WEATHER_LAYERS = [
      {
        label: "Precipitation",
        url: 'http://{s}.tile.openweathermap.org/map/precipitation_new/{z}/{x}/{y}.png?appid=????',
        attr: {attribution: '降水',
          opacity: 0.9
        }
      },

      {
        label: "Clouds",
        url: 'http://{s}.tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=????',
        attr: {attribution: '',
          opacity: 0.9
        }
      },

      {
        label: "Pressure",
        url: 'http://{s}.tile.openweathermap.org/map/pressure_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気圧',
          opacity: 0.9
        }
      },

      {
        label: "Wind",
        url: 'http://{s}.tile.openweathermap.org/map/wind_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速',
          opacity: 0.9
        }
      },
      
      {
        label: "Temperture",
        url: 'http://{s}.tile.openweathermap.org/map/temp_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気温',
          opacity: 0.9
        }
      }
    ];
    return WEATHER_LAYERS;

  }
  
  /**
   * OpenWeatherMap気象レイヤー Ver 2
   * Freeライセンスでは利用不可
   * @returns {Array}
   */
  getLeafletWeatherMapLayerArrayV2() {

    const WEATHER_LAYERS = [
      {
        label: "Precipitation",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/TA2/{z}/{x}/{y}.png?appid=????&fill_bound=true',
        attr: {attribution: '降水',
          opacity: 0.9
        }
      },

      {
        label: "Clouds",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/CL/{z}/{x}/{y}.png?appid=????&fill_bound=true',
        attr: {attribution: '',
          opacity: 0.9
        }
      },

      {
        label: "Pressure",
        url: 'https://{s}.tile.openweathermap.org/map/pressure_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気圧',
          opacity: 0.9
        }
      },

      {
        label: "Wind",
        url: 'https://{s}.tile.openweathermap.org/map/wind_new/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速',
          opacity: 0.9
        }
      },
      
      {
        label: "Wind with direction",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/WND/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '風速風向',
          opacity: 0.9
        }
      },
      
      {
        label: "Temparture",
        url: 'https://maps.openweathermap.org/maps/2.0/weather/TA2/{z}/{x}/{y}.png?appid=????',
        attr: {
          attribution: '気温',
          opacity: 0.9
        }
      }
    ];


    return WEATHER_LAYERS;

  }

}

// ****** 描画用メソッド ****** //

    // -- ベースレイヤー設定 -- //
    // -C
    const layersclass = new MapLayers();
    let leyers = layersclass.getLeafletBaseMapLayerArray();
    //alert(leyers.length);

    let baseMaps = {};
    let curkey = "";
    let objlayer;
    $.each(leyers, function (j, itm) {
      curkey = itm["label"];
      objlayer = L.tileLayer(itm["url"], itm["attr"]);
      baseMaps[curkey] = objlayer;

      //console.log("curkey:" + curkey);
      //console.log("LDTP:" + itm["ldtp"]);
    });

    // -- OpenWeatherMap設定 -- //
    // -C
    leyers = layersclass.getLeafletWeatherMapLayerArray();
    let weatherMaps = [];

    $.each(leyers, function (j, itm) {
      curkey = itm["label"];
      objlayer = L.tileLayer(itm["url"], itm["attr"]);
      weatherMaps[curkey] = objlayer;
    });


    // 天気選択を加えたレイヤーコントロール //
    L.control.layers(baseMaps, weatherMaps, /*{collapsed: false}*/).addTo(lmap);
    // ベースマップを乗せる //
    let baseadd = baseMaps[layerkey].addTo(lmap);

 

[ 画面例 ]

Leaflet Javascript マーカーツールチップのカスタマイズ

 

 

 

 

 

 

Leaflet Javascript マーカーツールチップのカスタマイズについて備忘録しておきます。

1) スタイルの設定
2) ツールチップにスタイルとコンテンツをセット
3) マーカーにバインド

[ コード例 ]

// ツールチップスタイルのセット //
const tooltipStyleWP = {direction: 
            "right",
            offset: L.point(-30, 24), // x, y <= のオフセット位置
            opacity: 0.8,
            permanent: isPermanetTooltip || isPermanentTarget ? true : false,
            className: "waypointTTClass" + CLASS_TAIL

          };

// ツールチップ、スタイルとコンテントのセット //
const ttp = L.tooltip(tooltipStyleWP).setContent(feature.properties.ident);

// マーカーアイコンのセット //
icn = L.icon({
            iconUrl: feature.properties.icon,
            iconSize: [12, 12]
          });

// マーカーにバインド //
L.marker(latlng, {icon: icn}).bindTooltip(ttp);

 

[ className CSS例 ]


      /* 飛行機マーカーツールチップ */
      /* 暗色 */
      .aircraftTTClass {
        background: transparent;
        border: 1px solid #FFFFFF;
        font-size: 13px;
        color: #FFFFFF;
        padding: 2px;
      }
      .leaflet-tooltip-left.aircraftTTClass::before {
        border-left-color: transparent;
      }
      .leaflet-tooltip-right.aircraftTTClass::before {
        border-right-color: transparent;
      }

      /* 明色 */
      .aircraftTTClassL {
        background: #f2f2f2;
        border: 1px solid navy;
        font-size: 13px;
        color: #222222;
        padding: 2px;
      }
      .leaflet-tooltip-left.aircraftTTClassL::before {
        border-left-color: transparent;
      }
      .leaflet-tooltip-right.aircraftTTClassL::before {
        border-right-color: transparent;
      }

      /* Waypointマーカーツールチップ */
      /* 暗色 */
      .waypointTTClass {
        background: transparent;
        border: 1px solid #FFFF00;
        font-size: 11px;
        color: #FFFF00;
        padding: 2px;
      }
      .leaflet-tooltip-left.waypointTTClass::before {
        border-left-color: transparent;
      }
      .leaflet-tooltip-right.waypointTTClass::before {
        border-right-color: transparent;
      }

      /* 明色 */
      .waypointTTClassL {
        background: transparent;
        border: 1px solid navy;
        font-size: 11px;
        color: #868600;
        padding: 2px;
      }
      .leaflet-tooltip-left.waypointTTClassL::before {
        border-left-color: transparent;
      }
      .leaflet-tooltip-right.waypointTTClassL::before {
        border-right-color: transparent;
      }  

[ 画面例 ]

 

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

Mapbox Cookbook【電子書籍】[ Bill Kastanakis ]
価格:3858円 (2023/1/19時点)

楽天で購入

 

 

GoogleMap Javascript でAntimeridianライン (太平洋上日付変更線越え線の適正化)

Leafletで国際線飛行機の航跡ラインを描画したところ、日付変更線を通過するラインがおかしいままなので(プラグインをラップして使うと正しくなるようですが、まだ調べ切れてないので)、利用頻度少なく、課金もさほどないと思い、GoogleMapを使ってみました。

[ 描画例 ]

GoogleMap

Leaflet

GoogleMap Javascript でGreatCircleライン

Leafletで国際線飛行機の航跡ラインを描画したところ、長距離のラインが直線のままなので(プラグインをラップして使うと球面線になるようですが、まだ調べ切れてないので)、利用頻度少なく、課金もさほどないと思い、GoogleMapを使ってみました。

オプションの設定で、グレートサークルが適用されます。

[ ポリラインオプション設定例 ]


// 線の設定 //
gmapS.data.setStyle({
        strokeColor: "#FFFF00", // 黄色
        strokeWeight: 2,
        geodesic: true         // 球面線
      });      

[ 描画画面例 ]
GoogleMap

Leaflet