2013-05-31 4 views
14

पर कई माउसओवर ईवेंट लागू करें मेरे पास नेटवर्क आरेख (बल-निर्देशित ग्राफ), एक स्कैटरप्लॉट और एक तालिका है जो सभी इंटरकनेक्टेड हैं (jsFiddle देखें)। मेरे पास माउसकॉवर घटनाओं के लिए जिस तरह से मैं चाहता हूं, उस पर काम कर रहे इंटरकनेक्शन हैं। मैं अपने कोड को संशोधित करना चाहता हूं ताकि जब मैं नेटवर्क आरेख में नोड को माउसवर करता हूं, न केवल मूसड-ओवर नोड हाइलाइट किया जाता है (और स्कैटरप्लॉट और टेबल में इसके कनेक्शन), लेकिन इसके तत्काल पड़ोसी नोड्स को भी हाइलाइट किया जाता है (साथ ही साथ स्कैटरप्लॉट और टेबल में उनके कनेक्शन के रूप में)।पड़ोसी (कनेक्टेड) ​​नोड्स

मैं मदद के लिए Highlight selected node, its links, and its children in a D3 force directed graph में जानकारी को देखा। कहीं भी (बिल्कुल सही नहीं है) मुझे एक फ़ंक्शन का एक उदाहरण मिला जो कनेक्टेड नोड्स को परिभाषित करने में मदद करता है, isConnected()

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

मैं शायद एक if() बयान के साथ मेरी माउसओवर घटनाओं में इस समारोह को शामिल करने,, ताकि मैं "पर प्रकाश डाला" है कि मैं चाहता हूँ सभी कर सकते हैं करना चाहते हैं। लेकिन, मैं डी 3 और जेएस के लिए नया हूं और मुझे यकीन नहीं है कि इसे कैसे सेट अप करें।

नीचे कोड का स्निपेट (jsFiddle से) कि मैं संशोधित करने के लिए चाहते हैं। मैं अन्य उदाहरणों के लिए किसी भी सुझाव या पॉइंटर्स की सराहना करता हूं।

var node = svg.selectAll(".node") 
    .data(graph.nodes) 
    .enter().append("g") 
    .attr("class", function(d) { return "node " + d.name + " " + d.location; }) 
    .call(force.drag) 
    .on("mouseover", function(d) { 
     // I would like to insert an if statement to do all of these things to the connected nodes 
     // if(isConnected(d, o)) { 
      d3.select(this).select("circle").style("stroke-width", 6); 
      d3.select(this).select("circle").style("stroke", "orange"); 
      d3.select(this).select("text").style("font", "20px sans-serif"); 
      d3.selectAll("rect." + d.location).style("stroke-width", 6); 
      d3.selectAll("rect." + d.location).style("stroke", "orange"); 
      d3.selectAll("text." + d.location).style("font", "20px sans-serif"); 
      d3.selectAll("tr." + d.name).style("background-color", "orange"); 
      //} 
     }) 
    .on("mouseout", function(d) { 
     // if(isConnected(d, o)) { 
      d3.select(this).select("circle").style("stroke-width", 1.5); 
      d3.select(this).select("circle").style("stroke", "gray"); 
      d3.select(this).select("text").style("font", "12px sans-serif"); 
      d3.selectAll("rect." + d.location).style("stroke-width", 1.5); 
      d3.selectAll("rect." + d.location).style("stroke", "gray"); 
      d3.selectAll("text." + d.location).style("font", "12px sans-serif"); 
      d3.selectAll("tr." + d.name).style("background-color", "white"); 
      //} 
     }); 

उत्तर

5
एक और परिदृश्य मैं एक ग्राफ डेटा संरचना में मेरी दृश्य वस्तुओं डाल दिया और है कि कुशलता से उचित आइटम अपडेट करने के लिए नेविगेट जाएगा में

। लेकिन यह डी 3 है, लेकिन इसलिए हम वही काम करेंगे, लेकिन हमारे द्वारा बनाई गई ग्राफ डेटा संरचना के बजाय हम डी 3 चयन का उपयोग करेंगे (जो ग्राफ की तरह हो सकता है लेकिन इसके लिए वे सरणी की तरह बहुत अधिक देखेंगे)। एल्गोरिदमिक रूप से यह दृष्टिकोण उतना कुशल नहीं होगा, लेकिन हमारे ग्राफ छोटे हैं।

तो काम कर पीछे की ओर मैं एक चयन है कि केवल उठाया नोड के पड़ोसी नोड्स शामिल चाहते है। मैं इसे सभी सर्किलों का चयन करके और फिर डी 3 चयन फ़िल्टर विधि का उपयोग करके ऐसा करने के लिए करूँगा ताकि वह केवल उन मंडलियों को कम कर सकें जो पड़ोसी हैं।

बेशक

तो मैं पड़ोसियों की सूची की आवश्यकता है, लेकिन कुछ अच्छा js सरणी तरीकों कि को कम कर सकते हैं। अंतिम प्रासंगिक कोड (माउसओवर में) भी है कि लंबे समय तक नहीं है - लेकिन मैं टिप्पणियों का एक गुच्छा जोड़ दिया है:

// Figure out the neighboring node id's with brute strength because the graph is small 
var nodeNeighbors = graph.links.filter(function(link) { 
    // Filter the list of links to only those links that have our target 
    // node as a source or target 
    return link.source.index === d.index || link.target.index === d.index;}) 
.map(function(link) { 
    // Map the list of links to a simple array of the neighboring indices - this is 
    // technically not required but makes the code below simpler because we can use   
    // indexOf instead of iterating and searching ourselves. 
    return link.source.index === d.index ? link.target.index : link.source.index; }); 

// Reset all circles - we will do this in mouseout also 
svg.selectAll('circle').style('stroke', 'gray'); 

// now we select the neighboring circles and apply whatever style we want. 
// Note that we could also filter a selection of links in this way if we want to 
// Highlight those as well 
svg.selectAll('circle').filter(function(node) { 
    // I filter the selection of all circles to only those that hold a node with an 
    // index in my listg of neighbors 
    return nodeNeighbors.indexOf(node.index) > -1; 
}) 
.style('stroke', 'orange'); 

तुम भी fiddle

मैं यहाँ महत्वपूर्ण d3 अवधारणा प्रासंगिक लगता है की कोशिश कर सकते जब आप किसी तत्व के साथ डेटा को जोड़ते हैं (आमतौर पर चयन पर डेटा() या डेटाम() विधियों का उपयोग करते हैं) तो वह डेटा उस तत्व के साथ चिपक जाता है और भविष्य के चयन हमेशा इसका उपयोग करेंगे।

अन्य पहलुओं को जोड़ने के लिए आप उन विशेषताओं को उसी तरह खींच सकते हैं और उन्हें d3 के माध्यम से लिंक कर सकते हैं।उदाहरण के लिए स्थान आयताकारों के लिए आप माउसओवर में जोड़ सकते हैं:

var nodeLocations = graph.links.filter(function(link) { 
     return link.source.index === d.index || link.target.index === d.index;}) 
    .map(function(link) { 
     return link.source.index === d.index ? link.target.location : link.source.location; }); 

d3.selectAll("rect").filter(function(node) { return nodeLocations.indexOf(node.location) > -1; }) .style("stroke", "cyan"); 
+0

यह सहायक है, लेकिन यह केवल नेटवर्क आरेख पर हाइलाइट करने वाले पड़ोसी को लागू करता है। मैं टेबल और मानचित्र में संबंधित बिट्स को हाइलाइट करना चाहता हूं। तो, उदाहरण के लिए, जब मैं ग्रुप ए को माउसवर करता हूं, तो मैं जिम, सैली और टॉम को नेटवर्क आरेख में सर्किल हाइलाइट करना चाहता हूं (आपका कोड इस पर संबोधित करता है), (2) तालिका में पंक्तियों को हाइलाइट किया गया, और (3) हाइलाइट किया गया मानचित्र में आयताकार। क्या आप भाग 2 और 3 के साथ मेरी मदद कर सकते हैं? –

+0

यह आपके आयतों की तरह दिखता है और शायद आपकी तालिका डेटा को उसी तरह से संबद्ध नहीं करती है जैसे डी 3। लेकिन ऐसा कोई कारण नहीं है कि आप वैसे भी डी 3 चयन का उपयोग नहीं कर सकते हैं। यह चाल अन्य वस्तुओं को हाइलाइट करने के लिए वास्तव में नोड्स या सही विशेषताओं की सूची प्राप्त करने के लिए पड़ोसी नोड इंडेक्स की सरणी का उपयोग करना होगा। तो आप एक ही तर्क लागू करने में सक्षम होना चाहिए। – Superboggly

+0

क्या आप मुझे यह संकेत दे सकते हैं कि यह कैसे करें? मैं \t की कोशिश की \t \t \t 'd3.selectAll (" रेक्ट। "+ D.location) .filter (समारोह (नोड) { वापसी nodeNeighbors.indexOf (node.index)> -1; }) .style (" स्ट्रोक "," सियान "); लेकिन, जाहिर है, यह काम नहीं किया। –

0

यह बात मैं बनाया है कि अहंकार नेटवर्क की सुविधा के साथ:

https://gist.github.com/emeeks/4588962

अपने नोड्स के लिए एक .on ("माउसओवर", findEgo) जोड़ें और निम्न, काम करना चाहिए जब तक चूंकि आपके पास यूआईडी विशेषता की पहचान करने की कोई तरह है, जिसे आप नोड्स लोड करते समय उत्पन्न कर सकते हैं यदि कोई आसान नहीं है। यह overkill का एक सा है, क्योंकि यह एन-डिग्री अहंकार नेटवर्क के लिए अनुमति देता है, और अन्य नेटवर्क विश्लेषण कार्यों के लिए किसी समेकित तालिका बनाता है, लेकिन बुनियादी कार्यक्षमता आप दे देंगे आप क्या चाहते हैं और आप या अन्य उपयोगकर्ताओं है कि पहलू उपयोगी लग सकते:

function findEgo(d) { 
    var computedEgoArray = findEgoNetwork(d.id, 1, false,"individual"); 
    d3.selectAll("circle.node").style("fill", function(p) {return p.id == d.id ? "purple" : computedEgoArray.indexOf(p.id) > -1 ? "blue" : "pink"}) 
} 

function findEgoNetwork(searchNode, egoNetworkDegree, isDirected, searchType) { 
    var egoNetwork = {}; 
    for (x in nodes) { 
    if (nodes[x].id == searchNode || searchType == "aggregate") { 
    egoNetwork[nodes[x].id] = [nodes[x].id]; 
    var z = 0; 
    while (z < egoNetworkDegree) { 
    var thisEgoRing = egoNetwork[nodes[x].id].slice(0); 
    for (y in links) { 
    if (thisEgoRing.indexOf(links[y].source.id) > -1 && thisEgoRing.indexOf(links[y].target.id) == -1) { 
    egoNetwork[nodes[x].id].push(links[y].target.id) 
    } 
    else if (isDirected == false && thisEgoRing.indexOf(links[y].source.id) == -1 && thisEgoRing.indexOf(links[y].target.id) > -1) { 
    egoNetwork[nodes[x].id].push(links[y].source.id) 
    } 
} 
z++; 
} 
} 
} 
if (searchType == "aggregate") { 
//if it's checking the entire network, pass back the entire object of arrays 
return egoNetwork; 
} 
else { 
//Otherwise only give back the array that corresponds with the search node 
return egoNetwork[searchNode]; 
} 
} 
संबंधित मुद्दे