2012-01-05 28 views
66

Tôi đang làm việc trên đồ thị có lực tác động trong D3. Tôi muốn làm nổi bật nút mouseover'd, các liên kết của nó và các nút con của nó bằng cách đặt tất cả các nút và liên kết khác thành độ mờ thấp hơn.Đánh dấu nút đã chọn, liên kết của nó và các nút con của nó trong đồ thị D3 hướng đạo lực

Trong ví dụ này, http://jsfiddle.net/xReHA/, tôi có thể làm mờ tất cả các liên kết và nút rồi mờ dần trong các liên kết được kết nối, nhưng cho đến nay, tôi không thể mờ nhạt một cách thanh lịch trong các nút được kết nối. của nút mouseover'd hiện tại.

Đây là chức năng quan trọng từ các mã:

function fade(opacity) { 
    return function(d, i) { 
     //fade all elements 
     svg.selectAll("circle, line").style("opacity", opacity); 

     var associated_links = svg.selectAll("line").filter(function(d) { 
      return d.source.index == i || d.target.index == i; 
     }).each(function(dLink, iLink) { 
      //unfade links and nodes connected to the current node 
      d3.select(this).style("opacity", 1); 
      //THE FOLLOWING CAUSES: Uncaught TypeError: Cannot call method 'setProperty' of undefined 
      d3.select(dLink.source).style("opacity", 1); 
      d3.select(dLink.target).style("opacity", 1); 
     }); 
    }; 
} 

Tôi nhận được một lỗi Uncaught TypeError: Cannot call method 'setProperty' of undefined khi tôi cố gắng để thiết lập opacity trên một yếu tố tôi tải từ source.target. Tôi nghi ngờ đây không phải là cách thích hợp để tải nút đó như một đối tượng d3, nhưng tôi không thể tìm cách khác để tải nó mà không cần lặp lại tất cả các nút một lần nữa để tìm các nút khớp với mục tiêu hoặc nguồn của liên kết. Để giữ hiệu suất hợp lý, tôi không muốn lặp lại tất cả các nút hơn mức cần thiết.

Tôi lấy ví dụ về mờ dần các liên kết từ http://mbostock.github.com/d3/ex/chord.html:

enter image description here

Tuy nhiên, điều đó không cho thấy làm thế nào để thay đổi các nút con được kết nối.

Bất kỳ gợi ý tốt về cách giải quyết hoặc cải thiện này sẽ được bỏ phiếu tán dữ dội :)

Trả lời

86

Lỗi này là bởi vì bạn đang lựa chọn các đối tượng dữ liệu (d.source và d.target) chứ không phải là yếu tố gắn liền với DOM những đối tượng dữ liệu đó.

Bạn đã có những dòng nổi bật làm việc, nhưng tôi có lẽ sẽ kết hợp mã của bạn vào một sự lặp lại duy nhất, như thế này:

link.style("opacity", function(o) { 
    return o.source === d || o.target === d ? 1 : opacity; 
}); 

Nêu bật các nút láng giềng là khó khăn hơn vì những gì bạn cần phải biết những người hàng xóm cho mỗi nút. Thông tin này không dễ xác định với các cấu trúc dữ liệu hiện tại của bạn, vì tất cả các bạn có như một mảng các nút và một mảng các liên kết. Quên DOM trong một giây, và tự hỏi làm thế nào bạn sẽ xác định xem hai nút ab là hàng xóm?

function neighboring(a, b) { 
    // ??? 
} 

Một cách tốn kém để làm điều đó là để lặp qua tất cả các liên kết và xem nếu có một liên kết kết nối a và b:.

function neighboring(a, b) { 
    return links.some(function(d) { 
    return (d.source === a && d.target === b) 
     || (d.source === b && d.target === a); 
    }); 
} 

(này giả định rằng liên kết là vô hướng Nếu bạn chỉ muốn làm nổi bật hàng xóm được kết nối về phía trước, sau đó loại bỏ nửa sau của OR.)

Cách hiệu quả hơn để tính toán điều này, nếu bạn phải thực hiện thường xuyên, là có bản đồ hoặc ma trận cho phép tra cứu hằng số để kiểm tra xem a và b có phải là hàng xóm hay không.Ví dụ:

var linkedByIndex = {}; 
links.forEach(function(d) { 
    linkedByIndex[d.source.index + "," + d.target.index] = 1; 
}); 

Bây giờ bạn có thể nói:

function neighboring(a, b) { 
    return linkedByIndex[a.index + "," + b.index]; 
} 

Và như vậy, bây giờ bạn có thể lặp qua các nút và cập nhật opacity của họ một cách chính xác:

node.style("opacity", function(o) { 
    return neighboring(d, o) ? 1 : opacity; 
}); 

(Bạn cũng có thể muốn đặc biệt là trường hợp liên kết di chuột qua, bằng cách đặt liên kết tự cho mỗi nút trong linkedByIndex hoặc bằng cách kiểm tra trực tiếp d khi tính toán kiểu hoặc bằng cách sử dụng a! Quan trọng css :hover kiểu.)

Điều cuối cùng tôi thay đổi trong mã của bạn là sử dụng độ mờ đục và độ mờ đục hơn là độ mờ đục, vì chúng cung cấp hiệu suất tốt hơn nhiều.

+1

Điều đó hoạt động tốt @mbostock, cảm ơn bạn rất nhiều: D Tôi đã cập nhật [jsfiddle] (http://jsfiddle.net/xReHA/1/) với giải pháp của bạn. –

+1

Đã xóa một cuộc gọi không cần thiết để tạo kiểu trên liên kết: http://jsfiddle.net/xReHA/2/ –

+0

Mike, giải pháp đó đơn giản là đẹp. Chỉ cần nói. – Vivek

Các vấn đề liên quan