【OpenSeadragon】 Googleマップのような地図を作りたい!

こんにちはKaorinです。
Googleマップは使わずに、地図画像にピンを立てたりヌルヌル動かせるプラグインを見つけたので紹介します。

もくじ

やりたいこと

  • 地図画像を(Googleマップのように)ドラッグでヌルヌル動かしてズームインアウトもさせたい
  • 指定した場所にピンを立てたい
  • 立てたピンにイベントを指定して情報をポップアップさせたい
  • Googleマップは使わない

実装方法

OpenSeadragon」というプラグインを使用しました。
トップページのサンプルがヌルヌル動いて期待できます。

OpenSeadragonはdziファイル(タイル状に画像を分けたデータ)などを取り扱うことができます(というかそれがこのプラグインの主な使い方です)。
画像をズームした時にタイルを随時読み込むデータです。そのようなデータを作る際はCreating Zooming Imagesを参考にしてください。dziファイルに関しては[JS] Deep Zoom Image 規格の画像生成と表示が分かりやすかったです。

今回はjpg画像をそのまま使う方法で実装します。dziファイルなどを使用する際は、OpenSeadragon APIを参考にどうぞ。

導入

地図画像をドラッグして動かしたりズームインアウトさせたいだけでしたら、導入はとても簡単です。

※一枚で実装する場合、5,000pxぐらいのデータだとiosで画像が表示されなくなるので注意が必要です。

<div id="mapWrap" style="width: 800px; height: 600px;"></div>
<script src="js/openseadragon.min.js"></script>
<script type="text/javascript">
    var viewer = OpenSeadragon({
		id: "mapWrap",
		prefixUrl: "/images/",
		tileSources: {
			type: 'image',
			url:  '/images/map/map.jpg',
			buildPyramid: false
		},
    });
</script>

参考

オプション

var viewer = OpenSeadragon({
	defaultZoomLevel: 1.4, //表示される画像サイズ。1はデフォルトサイズ
	visibilityRatio:0.9, //画像をドラッグして端にいった時の跳ね返りの制御(0~1)
	gestureSettingsMouse: //マウスポインタのイベント制御
		clickToZoom: false,//例えばクリックしてズームするのをfalseできる
	},
});

参考

Googleマップのようにピンを立てる

地図にはピンが欲しいですよね。
OpenSeadragon Class: Overlayを参考にすることでピンを立てることができます。ホバーイベントでポップアップ表示も可能です。

<img id="icon1" src="images/icon.svg" alt="アイコン">
<div class="mapWrap">
	<div id="icon1Tip">
		<p>ポップアップのテキスト</p>
	</div>
</div>
var viewer = OpenSeadragon({
	overlays:[
		{
		id: 'icon1',
		x: 0.47,//xyの値は下記の「ピンを立てる場所を確認する」で取得できる
		y: 0.62,
		placement: 'CENTER',
		checkResize: false,//ズームインアウトしてもアイコンのサイズを変えない
		className: 'highlight'
		},
	],
	onPageChange: function() {
		setTimeout(bindtooltip, 500);
	}		
});
$(function() {
	setTimeout(bindtooltip, 500);
});	
viewer.setControlsEnabled(true);
function bindtooltip(){
	var tip = $('#icon1Tip');
	$("#icon1").hover(function(e){
		var mousex = e.pageX + 20,
			mousey = e.pageY + 20,
			tipWidth = tip.width(),
			tipHeight = tip.height(),
			tipVisX = $(window).width() - (mousex + tipWidth),
			tipVisY = $(window).height() - (mousey + tipHeight);
		if ( tipVisX < 20 ) {
			mousex = e.pageX - tipWidth - 20;
		} if ( tipVisY < 20 ) {
			mousey = e.pageY - tipHeight - 20;
		}
		tip.css({  top: mousey, left: mousex, position: 'absolute' });
		tip.show().css({opacity: 0.8});
	}, function() {
		tip.hide();
	});
}

ピンを立てる座標を確認する

Viewportの値が画像内の座標になります。

    viewer.addHandler('open', function() {
		var positionEl = document.querySelectorAll('.info .position')[0];
        var tracker = new OpenSeadragon.MouseTracker({
            element: viewer.container,
            moveHandler: function(event) {
                var webPoint = event.position;
                var viewportPoint = viewer.viewport.pointFromPixel(webPoint);
                var imagePoint = viewer.viewport.viewportToImageCoordinates(viewportPoint);

                positionEl.innerHTML = 'Web:<br>' + webPoint.toString() + 
                    '<br><br>Viewport:<br>' + viewportPoint.toString() +
                    '<br><br>Image:<br>' + imagePoint.toString();
            }
        });  
        tracker.setTracking(true);  
    });	

参考

終わりに

OpenSeadragonを日本語で解説しているサイトがなかなか見つからず苦戦しましたが、すべての答えは公式サイトに書いてあるなあ(英語で!)ということを改めて知れました。

Googleマップのような地図を作りたい場合はOpenSeadragon一択でいいのではないかと思うほどシンプルで美しいプラグインでした。

実装する際に参考にしたサイト

Kaorin
まめなりでコーディング担当のかおりんです。 コーディングを楽しくできるように勉強したことを記事にしたいな。