2013-02-28 26 views
6

Đây có thể là trường hợp điển hình của "bạn đang làm sai", nhưng tất cả tìm kiếm của tôi cho đến nay chưa bảo đảm bất kỳ trợ giúp nào.Làm cách nào để điều chỉnh kích thước thu phóng cho một điểm trong D3?

Dưới đây là kịch bản của tôi:

Tôi đang sử dụng một phép chiếu bản đồ albersUSA kết hợp với các tập tin quốc gia và quận GeoJSON để vẽ tất cả mọi thứ.

Tôi cũng có tệp "thành phố" tự tạo chứa các thành phố lớn cho mỗi tiểu bang. Các tọa độ là chính xác và mọi thứ đều tốt.

enter image description here

Khi người dùng nhấp vào một trạng thái nhất định, tôi giấu tất cả các hình dạng trạng thái và sau đó tính toán các biến đổi cần thiết để có được hình dạng hạt cho trạng thái đó để phù hợp trong khung nhìn của tôi. Sau đó tôi áp dụng biến đổi đó cho tất cả các hình dạng hạt cần thiết để có chế độ xem "thu phóng". Mã của tôi là như sau:

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; 
} 

... và các chức năng ràng buộc

// 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

này hoạt động tốt ở đây, ngoại trừ cho các nước thực sự nhỏ, hệ số thu phóng là lớn hơn nhiều, và các vòng tròn bị phân tán.

enter image description here

Có cách nào để buộc các kích thước của các điểm đến được một kích thước cố định (ví dụ bán kính 15px) ngay cả sau khi chuyển đổi xảy ra?

Trả lời

5

Điều này xảy ra vì bạn đang thiết lập chuyển đổi tỷ lệ thay vì chia tỷ lệ vị trí. Bạn có thể thấy sự khác biệt here Về cơ bản nó là sự khác biệt giữa:

// 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; }); 

Với bản đồ có thể là bạn tốt nhất giải pháp là để tính toán quy mô bù đắp và của bạn khi bạn làm và sau đó thêm chúng vào của bạn chức năng chiếu - bạn muốn trực tiếp sửa đổi các giá trị x và y sau khi chiếu. Nếu bạn cập nhật chức năng chiếu đúng cách, bạn không cần phải làm bất cứ điều gì khác để áp dụng mức thu phóng thích hợp cho bản đồ của mình.

+0

Điều này có ý nghĩa! Tôi sẽ xem qua fiddle bạn cung cấp và làm cho nó hoạt động cho giải pháp của tôi. –

5

Đối với những thứ bạn không muốn chia tỷ lệ, chỉ cần chia nhỏ chúng theo 'tỷ lệ'. Trong trường hợp của tôi,

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); 

}); 
Các vấn đề liên quan