適当な画像をLeafletで表示してみます。画像はコレを使用します。
https://www.pakutaso.com/20200556146post-25030.html
画像をタイル状に変換
image-map-tilesのインストール
拡大縮小出来るようにするには、各ズーム倍率でタイル状にする必要があります。手作業ではやってられないので下記ツールを使用します。
https://www.npmjs.com/package/image-map-tiles
古くてGitHubのリンクも切れてる上、現状そのままで動かないのでパッチを当てます。
mkdir image-map-tiles
cd image-map-tiles
yarn init
echo nodeLinker: node-modules> .yarnrc.yml
patch-packageをインストールして、パッチファイルを配置。
yarn add -D patch-package postinstall-postinstall
package.json
に追記。
"scripts": {
"postinstall": "patch-package"
},
patches
フォルダを作成し、パッチファイル image-map-tiles+1.0.0.patch
を配置。
diff --git a/node_modules/image-map-tiles/index.js b/node_modules/image-map-tiles/index.js
index a18cae3..5d7c417 100644
--- a/node_modules/image-map-tiles/index.js
+++ b/node_modules/image-map-tiles/index.js
@@ -174,7 +174,7 @@ module.exports = function(imagePath, options) {
console.log(zoomPath, tileWidth, tileHeight);
console.log(metadata.width, metadata.height);
- var image = sharp(buffer);
+ //var image = sharp(buffer);
var num_columns = Math.ceil(metadata.width / tileWidth);
var num_rows = Math.ceil(metadata.height / tileHeight);
@@ -218,6 +218,7 @@ module.exports = function(imagePath, options) {
if (err) {
console.log(err);
} else {
+ var image = sharp(buffer);
image
.extract({ left: crop.x, top: crop.y, width: options.tileWidth, height: options.tileHeight })
.toFile(tilePath + crop.row + '.jpg', function(err){
@@ -254,7 +255,7 @@ module.exports = function(imagePath, options) {
thumbnail
.resize(250, 250)
- .crop(sharp.gravity.center)
+ //.crop(sharp.gravity.center)
.toFile(outputDir + 'thumbnail.jpg', function(err){
if (err) {
console.log('Thumbnail Error', err);
パッチの準備が出来たので、image-map-tiles をインストールする。インストール時に自動的にパッチがあたる。
yarn add -D image-map-tiles
画像をタイル状に変換する
入出力用のフォルダ input, output を作成し、inputに変換したい画像を入れておく。
入出力用のフォルダと同じ階層に main.js
を作成する。
const imageMapTiles = require('image-map-tiles');
let options = {
outputDir: "./output",
zoom: 4,
tileHeight: 256,
tileWidth: 256,
};
imageMapTiles("./input/AMEMAN1222044.jpg", options);
実行すると、outputフォルダに変換された画像が出来る。
node main.js
Leaflet上で表示する
タイル状になった画像を public
フォルダに格納しておきます。
マップコンポーネント
スタイルシートが無いと表示されないので作成する。
/* 地図を画面全体に表示 */
.leaflet-container {
width: 100vw;
height: 100vh;
}
/* 通常カーソル */
.leaflet-grab {
cursor: auto;
}
マップコンポートネントを作成。
'use client';
import { default as L } from 'leaflet';
import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png';
import markerIcon from 'leaflet/dist/images/marker-icon.png';
import markerIconShadow from 'leaflet/dist/images/marker-shadow.png';
import 'leaflet/dist/leaflet.css';
import { useEffect, useLayoutEffect, useState } from 'react';
import './customMap.css';
const DefaultIcon = L.icon({
iconUrl: markerIcon.src,
iconRetinaUrl: markerIcon2x.src,
shadowUrl: markerIconShadow.src,
iconAnchor: [12, 41], // アイコンのオフセット
popupAnchor: [0, -32], // ポップアップのオフセット
});
L.Marker.prototype.options.icon = DefaultIcon;
export default function CustomMap() {
const [layoutLoad, setLayoutLoad] = useState(false);
useLayoutEffect(() => {
return setLayoutLoad(true); // マップの再初期化を防ぐ
}, [layoutLoad]);
useEffect(() => {
if (!layoutLoad) return; // マップの再初期化を防ぐ
const map = L.map('map', {
crs: L.CRS.Simple,
maxZoom: 4,
});
map.setView(L.latLng(-256, 256), 0); // 初期位置
L.tileLayer('map/{z}/{x}/{y}.jpg', {
attribution:
'© <a href="https://www.pakutaso.com/20200556146post-25030.html">ぱくたそ</a>',
}).addTo(map);
// マーカー
L.marker(L.latLng(-512, 512), {
draggable: true,
}).addTo(map);
}, [layoutLoad]);
return (
<div className="leaflet-container">
<div id="map"></div>
</div>
);
}
ページ
作成したマップコンポーネントを読み込むわけですが、クライアントサイドでしか動かないので、ダイナミックインポートする。
'use client';
import dynamic from 'next/dynamic';
import { useMemo } from 'react';
export default function Home() {
const CustomMap = useMemo(
() =>
dynamic(() => import('./CustomMap'), {
loading: () => <p>map loading...</p>,
ssr: false,
}),
[]
);
return <CustomMap />;
}
実行する
実行して http://localhost:3000/custommap
にアクセスするとこんな感じに表示されます。
コメントを残す