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
セットアップ手順
- Node.jsのインストール
以下のサイトから「スタンドアローンのバイナリー(zip)」をダウンロードします。
https://nodejs.org/ja/download
node-v22.21.0-win-x64.zip をダウンロードして、C:\work\hoge に展開。
- コマンドプロンプト起動 & 作業フォルダへ移動
| cd \work\hoge\leaflet-drag-app |
- Node.jsにパスを通す
| set path=%path%;C:\work\hoge\node-v22.21.0-win-x64 |
- package.json作成
| npm init –yes |
- 必要ライブラリのインストール
| npm install –save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin npm install –save-dev style-loader css-loader npm install –save-dev leaflet leaflet-path-drag |
- src/hoge.js 作成
| import ‘leaflet/dist/leaflet.css’; import L from ‘leaflet’; import ‘leaflet-path-drag’; import ‘/src/hoge.css’; |
- src/hoge.css 作成
| .mycon { width:auto; height: auto; background: url(smile.svg) no-repeat center center/cover; } |
マーカー用定義。画像を使うようにしています。
- 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> |
地図クリックでマーカーが配置されるようにしています。
- 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”: { … } } |
- 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’, }, }; |
- webpack実行
npm run build
※cssで指定したアイコン画像は一緒にバンドルされるようにしています。
実行確認
| npx webpack-dev-server |
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>
プロジェクト一式も用意してあるので、興味ある方はぜひ参考にしてみてください!
※元文書を適当に作成しCopilotで生成