6

境界外のパンを許可したくない動的タイル セットがあります。

以下のコードは私を近づけますが、比較のためにマップの中心を使用するため、ユーザーは厳密な境界の外でも水平方向にスクロールできます

var strictBounds = new google.maps.LatLngBounds(
 new google.maps.LatLng(sw_lat, sw_lon), 
 new google.maps.LatLng(ne_lat, ne_lon)
);

google.maps.event.addListener(map, 'drag', 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));
});

何が起こっている

私が欲しいもの

4

3 に答える 3

9

すばやくアクセスできるように、このソリューションのjsfiddleは次のとおりです。http://jsfiddle.net/nYz6k/


中心に対する境界を検出する現在のソリューションに満足していると仮定すると、現在のマップキャンバスサイズに基づいて境界を制限するだけです。

現在取得している結果は、完全に制限されている場合(つまり、緯度と経度の両方が境界のコーナーを超えている場合)、制限境界のすべてのコーナーがマップの中央に表示されることです。

解決策は、実際に境界からxおよびyオフセットを削除し、それでも中心に対してチェックできるようにすることです(これは、他の境界ベースのチェックソリューションと比較して最も効率的なソリューションです)。

また、マップを初期化するとき、およびウィンドウのサイズを変更するときにのみ境界を制限する必要があります。つまり、パンするときに、すでに提供したチェックメソッド以外に余分な処理オーバーヘッドはありません。

マップのmaxZoomプロパティを設定することを忘れないでください(必要に応じて微調整してください)。これは、決定されたズームレベルを超えると、制限範囲自体がビューポートに収まり、その解決策がないためです。

重要!「drag」の代わりに「center_changed」を使用します。これは、「drag」には、ドラッグを終了して中心を設定したときに、マップがパンの方向にスライドするというスライド動作があるためです。


ソリューションを実装する前に、Maps APIの座標系と投影法がどのように機能するかを確認することをお勧めします。これは、このソリューションがそれに大きく基づいているためです。微調整する場合は、この情報を知っておくと便利です。

https://developers.google.com/maps/documentation/javascript/maptypesをクリックし、[カスタムマップタイプ]->[マップ座標]セクションを確認してください。


これがあなたがする必要があることです。まず、地理座標(LatLng)とピクセル座標を変換する2つの短い方法を実装する必要があります。

var fromLatLngToPixel = function (latLng) {
  var point = map.getProjection().fromLatLngToPoint(latLng);
  var zoom = map.getZoom();
  return new google.maps.Point(
    Math.floor(point.x * Math.pow(2, zoom)),
    Math.floor(point.y * Math.pow(2, zoom))
  );
}

var fromPixelToLatLng = function (pixel) {
  var zoom = map.getZoom();
  var point = new google.maps.Point(
    pixel.x / Math.pow(2, zoom),
    pixel.y / Math.pow(2, zoom)
  );
  return map.getProjection().fromPointToLatLng(point);
}

次に、境界を効果的に制限するメソッドを実装します。マップキャンバスのサイズが変更されるたびに結果の境界が変更されるため、元の境界を格納する変数を常に保持する必要があることに注意してください。

このために、originalBoundsがsw_lat、sw_longなどで指定した境界を保持し、shrinkedBoundsこのメソッドによって変更されたとします。strictBoundsに名前を変更して、メソッドで引き続き機能させることができますが、それはあなた次第です。これは、jQueryを使用してキャンバスオブジェクトの幅と高さを取得します。

var shrinkBounds = function () {
  zoom = map.getZoom();

  // The x and y offset will always be half the current map canvas
  // width and height respectively
  xoffset = $('#map_canvas').width() / 2;
  yoffset = $('#map_canvas').height() / 2;

  // Convert the bounds extremities to global pixel coordinates
  var pixswOriginal = fromLatLngToPixel(originalBounds.getSouthWest());
  var pixneOriginal = fromLatLngToPixel(originalBounds.getNorthEast());

  // Shrink the original bounds with the x and y offset
  var pixswShrinked = new google.maps.Point(pixswOriginal.x + xoffset, pixswOriginal.y - yoffset);
  var pixneShrinked = new google.maps.Point(pixneOriginal.x - xoffset, pixneOriginal.y + yoffset);

  // Rebuild the shrinkedBounds object with the modified 
  shrinkedBounds = new google.maps.LatLngBounds(
    fromPixelToLatLng(pixswShrinked),
    fromPixelToLatLng(pixneShrinked));
}

次に、あなたがしなければならないのはこのメソッドを呼び出すことです:

  • マップが初期化されるときに1回。メソッドを呼び出すタイミングによっては、マップがすべてのプロパティをまだ初期化していない可能性があるため、奇妙なエラーが発生する可能性があることに注意してください。最善の方法は、projection_changedイベントを使用することです。

    google.maps.event.addListener(map, 'projection_changed', function (e) {
      shrinkBounds();
    });
    
  • マップキャンバスのサイズが変更されるたび

     google.maps.event.addListener(map, 'resize', function (e) {
       shrinkBounds();
     });
    

ただし、これの最も重要な部分は、マップコンテナのプログラムによるサイズ変更に対して「サイズ変更」イベントがトリガーされないことです。したがって、プログラムでキャンバスのサイズを変更するたびに手動でトリガーする必要があります(そうする場合は、そうすることはできません)。 。

最も一般的な方法は、ウィンドウのサイズが変更されたときにトリガーすることです。

$(window).resize(function () {
  google.maps.event.trigger(map, 'resize');
});

これで、メソッドを安全に使用できるようになりましたが、前述のように「ドラッグ」ではなく「center_changed」のハンドラーとして使用できます。


完全に機能するコードを使用してjsfiddleをセットアップしました。

http://jsfiddle.net/nYz6k/

境界の南西隅に配置されている小さなハーフマーカーが表示されている左下隅に制限が表示されます。北西の角にも1つありますが、位置の上に表示されているので当然見えません。

于 2012-10-15T14:58:47.577 に答える
0

チェックとして map.getCenter() を使用する代わりに、map.getBounds() を使用します。

テストされていませんが、これを達成する簡単な方法は、両方の境界の結合が同一であるかどうかを確認することです (そうでない場合、マップの境界は厳密な境界の外にあります)。

var union = strictBounds.union(map.getBounds());
if (strictBounds.equals(union)) { //new map bounds is within strict bounds
于 2012-10-12T20:42:54.453 に答える