web-dev-qa-db-ja.com

Googleマップにd3パスをオーバーレイしますか?

D3.geoとGeoJsonを使用して、Googleマップに地図をオーバーレイしようとしています。私はなんとかd3にパスの描画にGoogleマップの投影法を使用させることができましたが、これは驚くほど簡単でした。ここに私がこれまで持っているものがあります:

http://www.caudillweb.com/temp/d3_choropleth.html

これは、ズームインおよびズームアウトするときにうまく機能します。

Map zoomed outMap zoomed in

しかし、パンすると、SVGオーバーレイも移動し、サイズが固定されているため、形状が切り捨てられます。

Map panned down

誰かがこのようなものを働かせましたか?私がここから行くことができるアイデアはありますか?上の例は、誰かがそれをいじりたい場合の単一の自己完結型HTMLファイルです。

35
Herb Caudill

この例 では、svgの幅と高さが8000 x 8000に設定されています。これは、ズームレベル9-10程度までは問題ないようです。上部と左側は、中央に配置するために-4000 x -4000に設定されています。最後に、svgの中心に描画されるように、投影がシフト/オフセットされます。

svgを拡大して中央に配置します:

.SvgOverlay svg {
    position: absolute;
    top: -4000px;
    left: -4000px;
    width: 8000px;
    height: 8000px;        
}

投影をオフセット:

return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000];
27
Derek Hunziker

1つのオプションは、初期マップサイズを非常に大きなもの、たとえば1000 x 1000ピクセル以上に設定することです。これにより、SVGオーバーレイが表示領域内に強制的にレンダリングされます(これは、Firefoxの制約のようです)。これはサイトのデザインに悪影響を与える可能性があるので、オーバーフローを隠すためにdivでマップをラップすることを検討してください。

#map-wrap {
    width: 500px;
    height: 500px;
    overflow: hidden;
}

#map {
    width: 1000px; /* just big enough to show the whole thing at zoom #6 */
    height: 1000px;
}

マップがレンダリングされたら、マップのサイズを500 x 500の希望のサイズに変更し、マップの中心を再設定できます。これはbounds_changedイベント:

google.maps.event.addListener(map, 'bounds_changed', function() {
    $map.css({ height: '500px', width: '500px' }); // back to desired dims
    google.maps.event.trigger(map, 'resize'); // trigger a 'refresh'
    map.setCenter(new google.maps.LatLng(-18.2, 35.1)); // re-center map
    google.maps.event.clearListeners(map, 'bounds_changed'); // don't do this again
});

これは実際の例です (FirefoxとChromeでテスト済み)。

いくつかの警告:

  1. 人々がズームインできるようにする距離が遠くなるほど、最初の「一時的な」マップをレンダリングする必要が大きくなります。たとえば、ズームレベル7を許可する場合は、補正するために初期マップを2000 x 2000にする必要がある場合があります。それほど大きなマップをレンダリングする場合、明らかにパフォーマンスの問題があります。分散が指摘したように、ズームレベルを制限するのが賢明かもしれません。
  2. ギリギリのサイズ変更のため、マップが再調整されるときにちらつきが発生します。 jQueryを使用して地図を非表示/表示するか、地図のサイズ変更が完了するまで、すべての上に白いオーバーレイを配置することを検討してください。
5
Derek Hunziker

私はsvgを大きくし、パディングを追加し、次のように上と左の位置を負にすることで、そのズームレベルで問題を修正することができました。

    .SvgOverlay, .SvgOverlay svg {
        position: absolute;
        top: -250px;
        left: -250px;
        padding: 500px;            
    }

    var svg = layer.append("svg")
          .attr("width", 1000)
          .attr("height", 1000)

ユーザーがさらにズームインできるようにする場合は、これらの数値をすべて増やす必要があります。たとえば、係数を10倍にすると、すべてのズームレベルの問題が解決するようです。ただし、さらにズームインするとsvgオーバーレイの有用性が低下するため、ユーザーのズーム機能を制限したい場合があります。

ここにFiddleアイデアを示しています。 http://jsfiddle.net/VHWqq/7/

編集:Herbが指摘しているように、このアプローチはFirefoxでは機能しません。

2
disperse