2013-02-28 8 views
6

これは「あなたが間違っている」という古典的なケースかもしれませんが、これまでの検索でも何の助けも得られていません。D3でポイントのズームサイズを調整するにはどうすればよいですか?

私はすべてを描画するために、国や県にGeoJSONファイルと一緒にalbersUSAの地図投影を使用しています:

は、ここに私のシナリオです。

私はまた、各州の主要都市を含む自己作成「都市」ファイルを持っています。座標は正確で、すべてが良く見えます。ユーザーが指定した状態でクリックすると

enter image description here

、私はすべての状態の形状を隠し、その状態が私のビューポート内に収まるようにするために、郡の形状を取得するために必要な変換を計算します。次に、「拡大」ビューを取得するために、必要な郡のすべての図形にその変換を適用します。私のコードは次のとおりです。

function CalculateTransform(objectPath) 
{ 
    var results = ''; 

    // Define bounds/points of viewport 
    var mapDimensions = getMapViewportDimensions(); 
    var baseWidth = mapDimensions[0]; 
    var baseHeight = mapDimensions[1]; 

    var centerX = baseWidth/2; 
    var centerY = baseHeight/2; 

    // Get bounding box of object path and calculate centroid and zoom factor 
    // based on viewport. 
    var bbox = objectPath.getBBox(); 
    var centroid = [bbox.x + bbox.width/2, bbox.y + bbox.height/2]; 
    var zoomScaleFactor = baseHeight/bbox.height; 
    var zoomX = -centroid[0]; 
    var zoomY = -centroid[1]; 

    // If the width of the state is greater than the height, scale by 
    // that property instead so that state will still fit in viewport. 
    if (bbox.width > bbox.height) { 
     zoomScaleFactor = baseHeight/bbox.width; 
    } 

    // Calculate how far to move the object path from it's current position to 
    // the center of the viewport. 
    var augmentX = -(centroid[0] - centerX); 
    var augmentY = -(centroid[1] - centerY); 

    // Our transform logic consists of: 
    // 1. Move the state to the center of the screen. 
    // 2. Move the state based on our anticipated scale. 
    // 3. Scale the state. 
    // 4. Move the state back to accomodate for the scaling. 
    var transform = "translate(" + (augmentX) + "," + (augmentY) + ")" + 
       "translate(" + (-zoomX) + "," + (-zoomY) + ")" + 
       "scale(" + zoomScaleFactor + ")" + 
       "translate(" + (zoomX) + "," + (zoomY) + ")"; 

    return results; 
} 

...と結合機能これは本当に小さな州を除いて、ここでうまく動作しenter image description here

// Load county data for the state specified. 
d3.json(jsonUrl, function (json) { 
    if (json === undefined || json == null || json.features.length == 0) 
    { 
     logging.error("Failed to retrieve county structure data."); 
     showMapErrorMessage("Unable to retrieve county structure data."); 
     return false; 
    } 
    else 
    { 
     counties.selectAll("path") 
       .data(json.features) 
       .enter() 
        .append("path") 
         .attr("id", function (d, i) { 
         return "county_" + d.properties.GEO_ID 
         }) 
         .attr("data-id", function (d, i) { return d.properties.GEO_ID }) 
         .attr("data-name", function (d, i) { return countyLookup[d.properties.GEO_ID] }) 
         .attr("data-stateid", function (d, i) { return d.properties.STATE }) 
         .attr("d", path); 

     // Show all counties for state specified and apply zoom transform. 
     d3.selectAll(countySelector).attr("visibility", "visible"); 
     d3.selectAll(countySelector).attr("transform", stateTransform); 

     // Show all cities for the state specified and apply zoom transform 
     d3.selectAll(citySelector).attr("visibility", "visible"); 
     d3.selectAll(citySelector).attr("transform", stateTransform); 
    } 
}); 

、ズーム倍率は、はるかに大きいですそして円は歪んだ。

enter image description here

変換が発生した後も、固定サイズ(たとえば15ピクセル半径)であるとの点の大きさを強制する方法はありますか?

答えて

5

これは、位置を拡大する代わりに縮尺変換を設定しているために起こります。あなたがして、あなたにそれらを追加すると、あなたは最良の解決策は、あなたのオフセット及びスケールを計算することであるおそらく

マッピングで
// Thick lines because they are scaled too 
var bottom = svg.append('g').attr('transform', 'scale('+scale+','+scale+')'); 
bottom.selectAll('circle') 
    .data(data) 
    .enter().append('circle') 
    .attr('cx', function(d) { return d.x; }) 
    .attr('cy', function(d) { return d.y; }); 

// line thicknesses are nice and thin 
var top = svg.append('g'); 
top.selectAll('circle') 
    .data(data) 
    .enter().append('circle') 
    .attr('cx', function(d) { return d.x * scale; }) 
    .attr('cy', function(d) { return d.y * scale; }); 

:あなたは違いhereは、基本的には違いあり見ることができます投影関数 - 投影後のxとyの値を直接変更したい。投影関数を適切に更新すると、マップに適切なズームを適用するために何もする必要はありません。

+0

これは意味があります!あなたが提供したフィドルを見て、それを私の解決のために働かせます。 –

5

スケールしたくないものについては、スケールで分割してください。私の場合、

var zoom = d3.behavior.zoom() 
    .on("zoom",function() { 
     g.attr("transform","translate("+d3.event.translate.join(",")+")scale("+d3.event.scale+")"); 

     g.selectAll(".mapmarker") 
     .attr("r",6/d3.event.scale) 
     .attr("stroke-width",1/d3.event.scale); 

}); 
関連する問題