XYZ 方式のタイルレイヤで、用意されていないズームレベルのタイルを、それより低い解像度のタイルで代用したいときがあります。地理院地図で細かい地図を表示したくないときや、容量やレンダリング負荷を減らしたい場合に有効なテクニックです。OpenLayers2 は不可能だと思って PHP で対応していたのですが、今回可能だということが分かったので紹介します。
OpenLayers2
serverResolutions にサーバーでサポートする解像度を配列で指定しておくと、それ以外のズームレベルで拡大表示が行われます。解像度は1ピクセル当たりのメートル単位になっており、下記ソースコードの配列で0~18の順で並んでいます。拡大表示を確認するには、下側の解像度をいくつかコメントアウトしてみてください。
var map = new OpenLayers.Map({
div: "map",
projection: "EPSG:3857",
displayProjection: "EPSG:4326",
numZoomLevels: 19,
layers: [
new OpenLayers.Layer.XYZ(
"GSI Maps",
"https://cyberjapandata.gsi.go.jp/xyz/std/${z}/${x}/${y}.png",
{
serverResolutions: [
156543.03390625,
78271.516953125,
39135.7584765625,
19567.87923828125,
9783.939619140625,
4891.9698095703125,
2445.9849047851562,
1222.9924523925781,
611.4962261962891,
305.74811309814453,
152.87405654907226,
76.43702827453613,
38.218514137268066
19.109257068634033,
9.554628534317017,
4.777314267158508,
2.388657133579254
1.194328566789627,
0.5971642833948135
]
}
)
],
center: new OpenLayers.LonLat(139, 37).transform("EPSG:4326", "EPSG:3857"),
zoom: 5
});
OpenLayers3
maxZoom にサーバーでサポートするズームレベルを指定すると、それ以外のズームレベルで拡大表示が行われます。下記ソースコードでは、ズームレベル11以上は10の拡大表示になります。
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
maxZoom: 10
})
})
],
view: new ol.View({
center: ol.proj.fromLonLat([139, 37]),
zoom: 5
})
});
Leaflet
Leaflet では maxNativeZoom を指定することで、同様の拡大表示を実現可能です。
PHP で無理やり対応(おまけ)
OpenLayers2 にはそういった機能が無いと思って、PHP で動的に拡大カットするラッパーを組んでしまいました。必要性が無くなったものの、他にも応用が効くコードかと思いますので公開しておきます。
- シンプルにするために、以下のコードでは入力パラメータをチェックしていませんのでご注意ください
- $max_zoom にはタイルレイヤで用意されている最大ズームレベルを入れてください
$z = $_REQUEST['z'];
$x = $_REQUEST['x'];
$y = $_REQUEST['y'];
$max_zoom = 12;
if ($z > $max_zoom) {
// $max_zoom のタイルを切り取って拡大する
$pw = pow(2,$z - $max_zoom);
$zz = $max_zoom;
$xx = floor($x / $pw);
$yy = floor($y / $pw);
$dw = 256;
$sw = floor($dw / $pw);
$sx = $x % $pw * $sw;
$sy = $y % $pw * $sw;
$path = "./layers/tile/{$zz}/{$xx}/{$yy}.png";
if (file_exists($path)) {
$src = imagecreatefrompng($path);
$dst = imagecreatetruecolor($dw,$dw);
imageAlphaBlending($dst,false);
imageSaveAlpha($dst,true);
$transparent = imageColorAllocateAlpha($dst, 0,0,0, 0);
imageFill($dst, 0,0, $transparent);
imagecopyresampled($dst, $src, 0,0, $sx,$sy, $dw,$dw, $sw,$sw);
imagepng($dst);
exit;
} else {
header("HTTP/1.1 404 Not Found");
exit;
}
} else {
// 実ファイルにリダイレクト
$url = "./layers/tile/{$z}/{$x}/{$y}.png";
header('Location: '.$url);
exit;
}
関連ページ