webpackを使ってleafletでPolygonをドラッグしてみる

こんにちは、猫好きリーマンのほげPGです。

今回はleaflet-path-dragでPolygonをドラッグしてみます。

Leafletで地図上のPolygonをドラッグできるようにするライブラリ「leaflet-path-drag」を使って、簡単なサンプルを作ってみました。

フォルダ構成(最終形)

C:\work\hoge
├─node-v22.21.0-win-x64
└─leaflet-drag-app
  ├─dis
  │ ├─bundle.js
  │ └─index.html
  ├─node_modules
  ├─src
  │ ├─hoge.css
  │ ├─hoge.js
  │ └─smile.svg
  ├─hoge.html
  ├─package.json
  ├─package-lock.json
  └─webpack.config.js

セットアップ手順

  1. Node.jsのインストール

以下のサイトから「スタンドアローンのバイナリー(zip)」をダウンロードします。
https://nodejs.org/ja/download
node-v22.21.0-win-x64.zip をダウンロードして、C:\work\hoge に展開。

  1. コマンドプロンプト起動 & 作業フォルダへ移動
  1. Node.jsにパスを通す
  1. package.json作成
  1. 必要ライブラリのインストール
  1. src/hoge.js 作成
import ‘leaflet/dist/leaflet.css’;
import L from ‘leaflet’;
import ‘leaflet-path-drag’;
import ‘/src/hoge.css’;
  1. src/hoge.css 作成
.mycon {
  width:auto;
  height: auto;
  background: url(smile.svg) no-repeat center center/cover;
}

マーカー用定義。画像を使うようにしています。

  1. hoge.html 作成
<!DOCTYPE html>
<html lang=”ja”>
<head>
    <meta charset=”UTF-8″>
    <meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
    <title>Leaflet.Path.Drag Sample</title>
</head>
<body>
    <h1>Leaflet.Path.Drag サンプル</h1>
    <div id=”map” style=”width:1000px; height:600px; border:solid;”></div>
    <script src=”bundle.js”></script>
 
<script>
const map = L.map(‘map’).setView([35.300510,139.482],16);
 
L.tileLayer(‘https://mt1.google.com/vt/lyrs=r&x={x}&y={y}&z={z}’, {
    attribution: “<a href=’https://developers.google.com/maps/documentation’ target=’_blank’>Google Map</a>”
}).addTo(map);
 
map.on(‘click’, function(e) {
    console.log(“click”, e.latlng);
    addMarker(e.latlng);
});
 
let polyLatlngs = [
    L.latLng(35.302421, 139.481166),
    L.latLng(35.302009, 139.479868),
    L.latLng(35.301002, 139.480544),
    L.latLng(35.301388, 139.482024),
];
let polygon = L.polygon(polyLatlngs, {
    draggable: true,
    color: ‘orange’,
    weight: 1,
    opacity: 1.0,
    fillColor: ‘green’,
    fillOpacity: 0.5,
}).addTo(map)
    .bindPopup(‘Drag.’)
    .openPopup();
polygon.on(‘dragend’, function(e) {
    console.log(‘dragend’, e);
});
 
function addMarker(latlng) {
    let icon = L.divIcon({
        className: ‘mycon’,
        iconSize: [30, 30],
    });
    let marker = L.marker(latlng, {
        draggable: true,
        icon: icon
    }).addTo(map);
    marker.on(‘dragstart’, function () {
      map.dragging.disable();
    });
    marker.on(‘dragend’, function () {
      map.dragging.enable();
    });
}
</script>
</body>
</html>

地図クリックでマーカーが配置されるようにしています。

  1. package.jsonの修正
{
  “name”: “leaflet-drag-app”,
  “version”: “1.0.0”,
  “description”: “”,
  “main”: “webpack.config.js”,
  “scripts”: {
    “build”: “webpack”,                         //追加行
    “test”: “echo \”Error: no test specified\” && exit 1″
  },
  “keywords”: [],
  “author”: “”,
  “license”: “ISC”,
  “devDependencies”: {
    …
  }
}
  1. webpack.config.js 作成
const path = require(‘path’);
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
 
module.exports = {
  mode: “development”,
  entry: ‘./src/hoge.js’,
  output: {
    filename: ‘bundle.js’,
    path: path.resolve(__dirname, ‘dist’),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [‘style-loader’, ‘css-loader’],
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: ‘asset’,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: ‘./hoge.html’,
    }),
  ],
  devServer: {
    static: ‘./dist’,
  },
};
  1. webpack実行

※cssで指定したアイコン画像は一緒にバンドルされるようにしています。

実行確認

http://localhost:8080/ にアクセスして確認

問題点

地図をクリックするとマーカーが配置され、マーカーをドラッグできるようにしています。ただし、単純にマーカーを作成してドラッグすると、地図自体も一緒にドラッグされてしまうという問題が発生しました。

そのため、dragstart と dragend イベントで地図の dragging を無効/有効に切り替えることで対応しています。

なぜ地図までドラッグされてしまうのかは、まだ要調査です…。

Webpackを使わないサンプルも

Webpackを使わないバージョンも作ってみましたが、こちらは特に問題なく動作しました。手軽に試したい方にはおすすめです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Leaflet.Path.Drag Sample</title>
</head>
<body>
    <h1>Leaflet.Path.Drag サンプル2</h1>
    <div id="map" style="width:1000px; height:600px; border:solid;"></div>
    <link rel="stylesheet" href="https://npmcdn.com/leaflet@1.2.0/dist/leaflet.css">
    <script src="https://npmcdn.com/leaflet@1.2.0/dist/leaflet.js"></script>
    <script src="https://leaflet.github.io/Path.Drag.js/src/Path.Drag.js"></script>

<script>
const map = L.map('map').setView([35.300510,139.482],16);

L.tileLayer('https://mt1.google.com/vt/lyrs=r&x={x}&y={y}&z={z}', {
    attribution: "<a href='https://developers.google.com/maps/documentation' target='_blank'>Google Map</a>"
}).addTo(map);

map.on('click', function(e) {
    console.log("click", e.latlng);
    addMarker(e.latlng);
});

let polyLatlngs = [
    L.latLng(35.302421, 139.481166),
    L.latLng(35.302009, 139.479868),
    L.latLng(35.301002, 139.480544),
    L.latLng(35.301388, 139.482024),
];
let polygon = L.polygon(polyLatlngs, {
    draggable: true,
    color: 'orange',
    weight: 1,
    opacity: 1.0,
    fillColor: 'green',
    fillOpacity: 0.5,
}).addTo(map)
    .bindPopup('Drag.')
    .openPopup();
polygon.on('dragend', function(e) {
    console.log('dragend', e);
});

function addMarker(latlng) {
    let marker = L.marker(latlng, {
        draggable: true
    }).addTo(map);
}
</script>
</body>
</html>

プロジェクト一式も用意してあるので、興味ある方はぜひ参考にしてみてください!

leaflet-drag-app.zip

※元文書を適当に作成しCopilotで生成