回答:
dragend
イベントをリッスンでき、マップが許可された境界の外にドラッグされた場合は、マップを内側に戻します。LatLngBounds
オブジェクトで許可される境界を定義し、contains()
メソッドを使用して、新しい緯度/経度の中心が境界内にあるかどうかを確認できます。
ズームレベルを非常に簡単に制限することもできます。
次の例について考えてみます。 Fiddle Demo
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Limit Panning and Zoom</title>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body>
<div id="map" style="width: 400px; height: 300px;"></div>
<script type="text/javascript">
// This is the minimum zoom level that we'll allow
var minZoomLevel = 5;
var map = new google.maps.Map(document.getElementById('map'), {
zoom: minZoomLevel,
center: new google.maps.LatLng(38.50, -90.50),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Bounds for North America
var strictBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(28.70, -127.50),
new google.maps.LatLng(48.85, -55.90)
);
// Listen for the dragend event
google.maps.event.addListener(map, 'dragend', function() {
if (strictBounds.contains(map.getCenter())) return;
// We're out of bounds - Move the map back within the bounds
var c = map.getCenter(),
x = c.lng(),
y = c.lat(),
maxX = strictBounds.getNorthEast().lng(),
maxY = strictBounds.getNorthEast().lat(),
minX = strictBounds.getSouthWest().lng(),
minY = strictBounds.getSouthWest().lat();
if (x < minX) x = minX;
if (x > maxX) x = maxX;
if (y < minY) y = minY;
if (y > maxY) y = maxY;
map.setCenter(new google.maps.LatLng(y, x));
});
// Limit the zoom level
google.maps.event.addListener(map, 'zoom_changed', function() {
if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel);
});
</script>
</body>
</html>
上記の例のスクリーンショット。この場合、ユーザーはさらに南または極東にドラッグできません。
center_changed
代わりにイベントに変更した場合、これは完全に機能しましたdragend
。
ズームレベルを制限するより良い方法は、イベントに反応するのではなく、minZoom
/ maxZoom
オプションを使用することでしょうか?
var opt = { minZoom: 6, maxZoom: 9 };
map.setOptions(opt);
または、マップの初期化中にオプションを指定できます。例:
var map = new google.maps.Map(document.getElementById('map-canvas'), opt);
朗報です。2019年2月14日にリリースされたMaps JavaScript APIのバージョン3.35以降、新しいrestriction
オプションを使用してマップのビューポートを制限できます。
ドキュメントによると
MapRestrictionインターフェース
マップに適用できる制限。マップのビューポートはこれらの制限を超えることはありません。
ソース:https : //developers.google.com/maps/documentation/javascript/reference/map#MapRestriction
したがって、マップの初期化中に制限オプションを追加するだけです。ビューポートをスイスに制限する次の例を見てください。
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 46.818188, lng: 8.227512},
minZoom: 7,
maxZoom: 14,
zoom: 7,
restriction: {
latLngBounds: {
east: 10.49234,
north: 47.808455,
south: 45.81792,
west: 5.95608
},
strictBounds: true
},
});
}
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap" async defer></script>
これが役に立てば幸いです!
範囲を制限するはるかに良い方法...上記のポスターのcontainsロジックを使用しました。
var dragStartCenter;
google.maps.event.addListener(map, 'dragstart', function(){
dragStartCenter = map.getCenter();
});
google.maps.event.addListener(this.googleMap, 'dragend', function(){
if (mapBounds.contains(map.getCenter())) return;
map.setCenter(this.dragStart);
});
this.googleMap
代わりに追加するのmap
ですか?またべきではないdragStart
ことdragStartCenter
?最後に何mapBounds
ですか?
これを使用して、マップを特定の場所に再配置できます。それは私が必要としたものです。
var MapBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(35.676263, 13.949096),
new google.maps.LatLng(36.204391, 14.89038));
google.maps.event.addListener(GoogleMap, 'dragend', function ()
{
if (MapBounds.contains(GoogleMap.getCenter()))
{
return;
}
else
{
GoogleMap.setCenter(new google.maps.LatLng(35.920242, 14.428825));
}
});
myOptions = {
center: myLatlng,
minZoom: 6,
maxZoom: 9,
styles: customStyles,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
これが、表示可能領域の制限の問題を解決するための私の変種です。
google.maps.event.addListener(this.map, 'idle', function() {
var minLat = strictBounds.getSouthWest().lat();
var minLon = strictBounds.getSouthWest().lng();
var maxLat = strictBounds.getNorthEast().lat();
var maxLon = strictBounds.getNorthEast().lng();
var cBounds = self.map.getBounds();
var cMinLat = cBounds.getSouthWest().lat();
var cMinLon = cBounds.getSouthWest().lng();
var cMaxLat = cBounds.getNorthEast().lat();
var cMaxLon = cBounds.getNorthEast().lng();
var centerLat = self.map.getCenter().lat();
var centerLon = self.map.getCenter().lng();
if((cMaxLat - cMinLat > maxLat - minLat) || (cMaxLon - cMinLon > maxLon - minLon))
{ //We can't position the canvas to strict borders with a current zoom level
self.map.setZoomLevel(self.map.getZoomLevel()+1);
return;
}
if(cMinLat < minLat)
var newCenterLat = minLat + ((cMaxLat-cMinLat) / 2);
else if(cMaxLat > maxLat)
var newCenterLat = maxLat - ((cMaxLat-cMinLat) / 2);
else
var newCenterLat = centerLat;
if(cMinLon < minLon)
var newCenterLon = minLon + ((cMaxLon-cMinLon) / 2);
else if(cMaxLon > maxLon)
var newCenterLon = maxLon - ((cMaxLon-cMinLon) / 2);
else
var newCenterLon = centerLon;
if(newCenterLat != centerLat || newCenterLon != centerLon)
self.map.setCenter(new google.maps.LatLng(newCenterLat, newCenterLon));
});
strictBounds
new google.maps.LatLngBounds()
タイプのオブジェクトです。self.gmap
Google Mapオブジェクト(new google.maps.Map()
)を格納します。
それは実際に機能しますが、境界がそれらをカバーする場合は、0番目の経線と緯線を横切る痔を考慮することを忘れないでください。
何らかの理由で
if (strictBounds.contains(map.getCenter())) return;
私にはうまくいきませんでした(おそらく南半球の問題)。私はそれを次のように変更する必要がありました:
function checkBounds() {
var c = map.getCenter(),
x = c.lng(),
y = c.lat(),
maxX = strictBounds.getNorthEast().lng(),
maxY = strictBounds.getNorthEast().lat(),
minX = strictBounds.getSouthWest().lng(),
minY = strictBounds.getSouthWest().lat();
if(x < minX || x > maxX || y < minY || y > maxY) {
if (x < minX) x = minX;
if (x > maxX) x = maxX;
if (y < minY) y = minY;
if (y > maxY) y = maxY;
map.setCenter(new google.maps.LatLng(y, x));
}
}
それが誰かを助けることを願っています。
1つの解決策は、特定の緯度/経度を知っている場合です。
google.maps.event.addListener(map, 'idle', function() {
map.setCenter(new google.maps.LatLng(latitude, longitude));
map.setZoom(8);
});
特定の緯度/経度がない場合
google.maps.event.addListener(map, 'idle', function() {
map.setCenter(map.getCenter());
map.setZoom(8);
});
または
google.maps.event.addListener(map, 'idle', function() {
var bounds = new google.maps.LatLngBounds();
map.setCenter(bounds.getCenter());
map.setZoom(8);
});
2016年半ば以降、表示可能な領域を制限する公式な方法はありません。ただし、境界を制限するアドホックソリューションのほとんどには欠陥があります。それらはマップビューに合うように境界を正確に制限しないため、マップの中心が指定された境界の外にある場合にのみ制限します。私のように境界をオーバーレイ画像に制限したい場合、これにより、下に示すような動作が発生し、アンダーレイマップが画像オーバーレイの下に表示されます。
この問題に取り組むために、ライブラリを作成しました。これにより、境界を正常に制限して、オーバーレイからパンできないようにします。
ただし、他の既存のソリューションと同様に、「振動する」問題があります。ユーザーがマップを十分に積極的にパンした場合、マウスの左ボタンを離した後も、マップはそれ自体でパンを続け、徐々に遅くなります。私はいつも地図を境界線に戻しますが、それは一種の振動をもたらします。このパン効果は、現時点ではJs APIが提供する手段で止めることはできません。googleがmap.stopPanningAnimation()などのサポートを追加するまで、スムーズなエクスペリエンスを作成することはできないようです。
上記のライブラリを使用した例、私が得ることができた最もスムーズで厳密な境界の経験:
function initialise(){
var myOptions = {
zoom: 5,
center: new google.maps.LatLng(0,0),
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
var map = new google.maps.Map(document.getElementById('map'), myOptions);
addStrictBoundsImage(map);
}
function addStrictBoundsImage(map){
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(62.281819, -150.287132),
new google.maps.LatLng(62.400471, -150.005608));
var image_src = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
var strict_bounds_image = new StrictBoundsImage(bounds, image_src, map);
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("maps", "3",{other_params:"sensor=false"});
</script>
<body style="margin:0px; padding:0px;" onload="initialise()">
<div id="map" style="height:400px; width:500px;"></div>
<script type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script>
</body>
ライブラリは、最小ズーム制限を自動的に計算することもできます。次に、minZoom
マップの属性を使用してズームレベルを制限します。
うまくいけば、これは与えられた境界を完全に尊重し、それらからパンすることを許可したくないソリューションを望んでいる誰かを助けるでしょう。
これは役に立ちます。
var myOptions = {
center: new google.maps.LatLng($lat,$lang),
zoom: 7,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
ズームレベルは、要件に応じてカスタマイズできます。
e.g. only between levels 6 and 9
に制限することに関する元の質問には対応していません。デフォルトのズームレベルを設定し、少しやり過ぎであるデフォルトのUI(つまり+
/ -
)を削除します。
if (x < minX) x = minX;
、if (x > maxX) x = maxX;
お互いを排除しないのですか?中心の座標ではないのに、キャンバスをminX / maxXおよびmaxX / maxY座標の中心に配置するのはなぜですか?