※パソコン(大画面)の方が見やすいです。

「OpenStreetMap」サンプルの作成

2026/11/14 16:29:12作成
2026/11/14 18:07:44更新

この度、無料の地図「OpenStreetMap」でgoogleの地図と同じようなことができるのかという実験をしてみました。その結果が以下の通りです。今回はほとんどAIによるコード変換でそのまま貼り付けたような次第です。

手順は次の通りです。
  1. 地図APIに頼らず、自分のサーバーで日本地図を表示する。からjapan-20260806.js とjapan-20260806.pmtilesファイルをダウンロードし、xoopsのルートディレクトリにosmというフォルダを作りその中に設置します。
  2. japan-20260806.jsを開き、6行目の部分を
    {
        "version": 8,
        "name": "Japan 2026/08/06",
        "sources": {
            "openmaptiles": {
                "url": "pmtiles://../../osm/japan-20260806.pmtiles", ←ここ
                "type": "vector",
                "attribution": "Date 2026/08/06 / © OpenStreetMap contributors"
            }
        },
    と変更します
  3. picoモジュールで記事を投稿します
これで以下のコードを貼り付ければ表示することができました。
○○周辺地図の表示
○○周辺地図地名
  1. 姫路城(地名を入れます)
<style>
  .osm-wrap {
    width: 100%;
    border: 2px solid #008000;
    background-color: #fffccc;
    box-sizing: border-box;
    font-size: 14px;
    line-height: 1.5;
    margin: 10px 0;
  }
  .osm-wrap * {
    box-sizing: border-box;
  }
  .osm-title {
    background-color: #008000 !important;
    color: #ffffff !important;
    text-align: center;
    font-size: 18px;
    font-weight: bold;
    padding: 8px 10px;
    margin: 0;
  }
  .osm-body {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
  }
  .osm-map-col {
    width: 75%;
    min-width: 300px;
    flex-grow: 1;
    position: relative;
  }
  #map_canvas {
    width: 100% !important;
    height: 480px !important;
    position: relative;
    overflow: hidden;
  }
  .osm-list-col {
    width: 25%;
    min-width: 200px;
    background-color: #fffccc;
    border-left: 2px solid #008000;
    padding: 8px;
    display: flex;
    flex-direction: column;
  }
  .osm-list-header {
    text-align: center;
    font-size: 13px;
    font-weight: bold;
    color: #333333 !important;
    background-color: #e6e8fa;
    border: 1px solid #c5cae9;
    padding: 5px;
    margin-bottom: 6px;
  }
  .osm-list-col ol {
    list-style-position: inside;
    list-style-type: upper-alpha;
    margin: 0 !important;
    padding: 0 4px !important;
    font-size: 13px;
    height: 420px;
    overflow-y: auto;
    text-align: left;
  }
  .osm-list-col li {
    padding: 4px 2px;
    border-bottom: 1px dashed #dcd8a8;
    color: #333333;
  }
  .osm-list-col li a {
    color: #0066cc !important;
    text-decoration: underline;
    cursor: pointer;
  }
  .osm-list-col li a:hover {
    color: #cc0000 !important;
  }
  .osm-list-col li:has(a:empty) {
    display: none;
  }
  .custom-pin {
    width: 26px;
    height: 26px;
    background-color: #e53935;
    color: #ffffff !important;
    font-weight: bold;
    font-size: 13px;
    font-family: Arial, sans-serif;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #ffffff;
    box-shadow: 0 2px 5px rgba(0,0,0,0.45);
    cursor: pointer;
    line-height: 1;
  }
  .custom-pin:hover {
    background-color: #b71c1c;
    transform: scale(1.12);
  }
  .maplibregl-popup-close-button {
    font-size: 20px !important;
    font-weight: bold !important;
    color: #555555 !important;
    padding: 2px 8px !important;
    line-height: 1.2 !important;
    background: transparent !important;
    border: none !important;
    cursor: pointer !important;
  }
  .maplibregl-popup-close-button:hover {
    color: #000000 !important;
    background-color: #eeeeee !important;
  }
  .maplibregl-popup-content {
    color: #222222 !important;
    font-size: 13px;
    line-height: 1.5;
    padding: 12px 28px 12px 14px !important;
    border-radius: 6px;
    box-shadow: 0 3px 10px rgba(0,0,0,0.25);
  }
  @media screen and (max-width: 680px) {
    .osm-map-col, .osm-list-col {
      width: 100% !important;
      min-width: 100% !important;
    }
    .osm-list-col {
      border-left: none !important;
      border-top: 2px solid #008000 !important;
    }
    #map_canvas {
      height: 360px !important;
    }
    .osm-list-col ol {
      height: auto !important;
      max-height: 220px;
    }
  }
</style>
<div class="osm-wrap">
  <div class="osm-title">○○周辺地図の表示</div>
  <div class="osm-body">
    <div class="osm-map-col">
      <div id="map_canvas"></div>
    </div>
    <div class="osm-list-col">
      <div class="osm-list-header">○○周辺地図地名</div>
      <ol>
        <li id="mark_0"><a href="javascript:void(0)" onclick="this.blur()">姫路城(地名を入れます)</a></li>
        <li id="mark_1"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_2"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_3"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_4"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_5"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_6"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_7"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_8"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_9"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_10"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_11"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_12"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_13"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_14"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_15"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_16"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_17"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_18"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_19"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_20"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_21"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_22"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_23"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_24"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
        <li id="mark_25"><a href="javascript:void(0)" onclick="this.blur()"></a></li>
      </ol>
    </div>
  </div>
</div>
<script>
window.addEventListener('load', function() {
  var cdnHost = "https:" + "//unpkg.com";

  var css = document.createElement("link");
  css.rel = "stylesheet";
  css.href = cdnHost + "/maplibre-gl@3.6.2/dist/maplibre-gl.css";
  document.head.appendChild(css);

  var s1 = document.createElement("script");
  s1.src = cdnHost + "/maplibre-gl@3.6.2/dist/maplibre-gl.js";
  s1.onload = function() {
    var s2 = document.createElement("script");
    s2.src = cdnHost + "/pmtiles@3.2.0/dist/pmtiles.js";
    s2.onload = startMap;
    document.head.appendChild(s2);
  };
  document.head.appendChild(s1);

  function startMap() {
    const protocol = new pmtiles.Protocol();
    maplibregl.addProtocol("pmtiles", protocol.tile);

    // 1. 地図の初期中心座標 [緯度, 経度] とズーム
    const centerLat = 34.83867476538625;
    const centerLng = 134.6945285797119;
    const initialZoom = 13;

    // 2. 各マーカーの座標 [緯度, 経度](空の [] はスキップされます)
    const myMarkPosition = [
      [34.83944857495147, 134.693915694952], // A (0)
      [], [], [], [], [], [], [], [], [],
      [], [], [], [], [], [], [], [], [], [],
      [], [], [], [], [], []
    ];

    // 3. 各情報ウィンドウ(吹き出し)の内容
    const myInfo = [
      '例)ここが姫路城ですよ', // A (0)
      '', '', '', '', '', '', '', '', '',
      '', '', '', '', '', '', '', '', '', '',
      '', '', '', '', '', ''
    ];

    const currentPath = location.pathname;
    const rootDir = currentPath.substring(0, currentPath.indexOf("/modules/"));

    fetch(rootDir + "/osm/japan-20260806.json")
      .then(function(res) { return res.json(); })
      .then(function(styleData) {
        if (styleData.sources && styleData.sources.openmaptiles) {
          styleData.sources.openmaptiles.url = "pmtiles://" + rootDir + "/osm/japan-20260806.pmtiles";
        }

        const map = new maplibregl.Map({
          container: 'map_canvas',
          style: styleData,
          center: [centerLng, centerLat],
          zoom: initialZoom,
          localIdeographFontFamily: "sans-serif"
        });

        map.on('load', function() {
          map.resize();
        });

        map.addControl(new maplibregl.NavigationControl(), 'top-right');

        const activePopup = new maplibregl.Popup({ offset: 16 });

        for (let i = 0; i < myMarkPosition.length; i++) {
          const pos = myMarkPosition.at(i);
          if (!pos || pos.length < 2 || !pos.at(0) || !pos.at(1)) continue;

          const lat = pos.at(0);
          const lng = pos.at(1);
          const letter = String.fromCharCode("A".charCodeAt(0) + i);

          const el = document.createElement('div');
          el.className = 'custom-pin';
          el.textContent = letter;

          new maplibregl.Marker({ element: el })
            .setLngLat([lng, lat])
            .addTo(map);

          const showPopup = function(e) {
            if (e) e.stopPropagation();
            if (activePopup.isOpen() && activePopup.getLngLat().lng === lng && activePopup.getLngLat().lat === lat) {
              activePopup.remove();
              return;
            }
            activePopup
              .setLngLat([lng, lat])
              .setHTML(myInfo.at(i) || '')
              .addTo(map);
          };

          el.addEventListener('click', showPopup);

          const markLink = document.getElementById("mark_" + i);
          if (markLink) {
            markLink.addEventListener('click', showPopup);
          }
        }

        map.on('click', function() {
          activePopup.remove();
        });
      });
  }
});
</script>

投票数:0 平均点:0.00

趣味を楽しもう新着記事

欲しい商品が必ず見つかるメジャーなネットショップ

ログイン

オンライン状況

45 人のユーザが現在オンラインです。 - 1 人のユーザが 趣味を楽しもう を参照しています。.

登録ユーザ 0 ゲスト 45

Facebookリンク表示

検索

アクセスカウンタ

今日 : 929
昨日 : 2637
総計 : 2987573