2012-01-05 21 views
66

D3'te güçle yönlendirilmiş bir grafik üzerinde çalışıyorum. Diğer tüm düğümleri ve bağlantıları daha düşük bir opaklığa ayarlayarak mouseover'd düğümünü, bağlantılarını ve çocuk düğümlerini vurgulamak istiyorum.Seçilen düğümü, onun bağlantılarını ve çocuklarını D3 kuvvet yönelimli bir grafikte vurgulayın

Bu örnekte, http://jsfiddle.net/xReHA/, bağlantıların tüm düğümlerini ve düğümlerini devre dışı bıraktım, sonra bağlı bağlantılarda soldu, ancak şu ana kadar, çocuklar olan bağlı düğümlerde zarif bir şekilde soluyamadım. Şu anda mouseover'd düğümün.

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

ben source.target yüklenen bir elemanda saydamlığını ayarlamak denediğimde Uncaught TypeError: Cannot call method 'setProperty' of undefined hatası alıyorum:

Bu koddan anahtar işlevidir. Bu düğümün bir d3 nesnesi olarak yüklenmesinin doğru yolu olmadığından şüpheleniyorum, ancak bağlantının hedefiyle veya kaynağında eşleşenleri bulmak için tüm düğümler üzerinde tekrar yinelemeden başka bir yol bulamıyorum. Performansı makul tutmak için, tüm düğümlerde gerekli olandan daha fazla yineleme yapmak istemiyorum.

ben http://mbostock.github.com/d3/ex/chord.html bağlantıları solan örneğini aldı:

enter image description here

Ancak, bağlı alt düğümleri değiştirmeye göstermek gelmez.

çözmek veya bu nasıl geliştirilebileceğine ilişkin herhangi iyi önerileri

öfkeyle upvoted edilecektir :)

sen ilişkili veri nesneleri (d.source ve d.target) ziyade DOM öğelerini seçerek çünkü

cevap

86

hatadır Bu veri nesneleri.

Sen çalışma vurgulayarak hattım var ama muhtemelen böyle, tek bir yineleme içine kodunuzu birleştirmek olacaktır: sizin için komşular bilmeniz gerekenler çünkü

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

komşu düğümleri vurgulama zordur her düğüm. Bu bilgi, mevcut veri yapılarınızla kolayca tespit edilemez, çünkü bir dizi düğüm ve bir dizi bağlantı olarak sahip olduğunuzdan. DOM'ı bir saniyeliğine unutun ve iki düğümün a ve b'un komşuları olup olmadığını nasıl belirleyeceğinizi kendinize sorun. a ve b bağlayan bir bağlantı varsa

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

bunu Pahalı bir yolu bağlantıları üzerinde yineleme ve görmektir.

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

(Bu bağlantılar yönsüz olduğu düşünülürse sadece ileri-bağlantılı komşuları vurgulamak, sonra da OR'in ikinci yarısını ortadan kaldırmak istiyorsunuz.)

Bunu daha verimli bir şekilde hesaplamak, eğer sık ​​sık yapmanız gerekiyorsa, bir harita veya matrisin olması gerekir. a ve b'nin komşu olup olmadığını sınamak için sabit zamanlı arama.Örneğin:

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

Ve böylece, artık doğru kendi donukluk düğümler üzerinde yineleme ve güncelleyebilirsiniz: Şimdi

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

diyebilirsiniz

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

(Ayrıca isteyebilirsiniz her bir düğüm için linkedByIndex nolu her düğüm için bir self-link ayarlayarak ya da stili hesaplarken doğrudan d'u test ederek ya da a! important css :hover style.)

Kodunuzda değiştirdiğim son şey, opaklıktan ziyade dolgu-opaklık ve kontur-opaklık kullanmaktır çünkü bunlar daha iyi performans sunar.

+1

Bu harika @mbostock çalışıyor, çok teşekkür ederim: D [jsfiddle] (http://jsfiddle.net/xReHA/1/) çözümünüzle güncelledik. –

+1

Bağlantının tarzına gereksiz bir çağrıyı kaldırdı: http://jsfiddle.net/xReHA/2/ –

+0

Mike, bu çözüm çok güzeldi. Sadece söylüyorum'. – Vivek