How to make one function instead of 3 or more for a visualization in d3 to then add highlight when hovering over nodes

poweredbygt

I have visualized 3 trees with d3 but I have repeated my code, and now I want to add highlighting the same nodes in different trees when hovering over a node in a tree but this I cannot do as I see with this structure of code that I have now.

The d3 code I have now for the three different trees (so I have put the code three times in three different functions draw(), draw1() and draw2()):

<script>

//here i get the data
var data = {{data.chart_data | safe }}    

draw("#svg1", "#url");
draw1("#svg2", "#url");
draw2("#svg3", "#url");
draw3("#svg4", "#url");

function draw(selector, url){

    console.log(data);

    // ************** Generate the tree diagram  *****************
var margin = {top: 40, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;

var i = 0;

var tree = d3.layout.tree()
    .size([height, width]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x, d.y]; });

var svg = d3.select(selector).append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

root = data[0]

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 100; });

  // Declare the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { 
          return "translate(" + d.x + "," + d.y + ")"; });

  nodeEnter.append("circle")
      .attr("r", 10)
      .style("fill", "#fff");

  nodeEnter.append("text")
      .attr("y", function(d) { 
          return d.children || d._children ? -18 : 18; })
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function(d) { return d.cues; })
      .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter the links.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", diagonal);

  }
};


// Second tree
function draw1(selector, url){


    console.log(data);

    // ************** Generate the tree diagram  *****************
var margin = {top: 40, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;

var i = 0;

var tree = d3.layout.tree()
    .size([height, width]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x, d.y]; });

var svg = d3.select(selector).append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

root = data[1]

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 100; });

  // Declare the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { 
          return "translate(" + d.x + "," + d.y + ")"; });

  nodeEnter.append("circle")
      .attr("r", 10)
      .style("fill", "#fff");

  nodeEnter.append("text")
      .attr("y", function(d) { 
          return d.children || d._children ? -18 : 18; })
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function(d) { return d.cues; })
      .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter the links.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", diagonal);

  }
};


// third tree
function draw2(selector, url){

    console.log(data);

    // ************** Generate the tree diagram  *****************
var margin = {top: 40, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;

var i = 0;

var tree = d3.layout.tree()
    .size([height, width]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x, d.y]; });

var svg = d3.select(selector).append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

root = data[2]

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 100; });

  // Declare the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { 
          return "translate(" + d.x + "," + d.y + ")"; });

  nodeEnter.append("circle")
      .attr("r", 10)
      .style("fill", "#fff");

  nodeEnter.append("text")
      .attr("y", function(d) { 
          return d.children || d._children ? -18 : 18; })
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function(d) { return d.cues; })
      .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter the links.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", diagonal);

  }
};


// fourth tree
function draw3(selector, url){


    console.log(data);

    // ************** Generate the tree diagram  *****************
var margin = {top: 40, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;

var i = 0;

var tree = d3.layout.tree()
    .size([height, width]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x, d.y]; });

var svg = d3.select(selector).append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

root = data[3]

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 100; });

  // Declare the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { 
          return "translate(" + d.x + "," + d.y + ")"; });

  nodeEnter.append("circle")
      .attr("r", 10)
      .style("fill", "#fff");

  nodeEnter.append("text")
      .attr("y", function(d) { 
          return d.children || d._children ? -18 : 18; })
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function(d) { return d.cues; })
      .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter the links.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", diagonal);

  }
};
</script>

(notice that the only change is the root = data[] for every tree, so that I can access different elements of the list). Can this be done differently so that I have only one function draw() and I change the root = data[0] dynamically in d3? And then as I said previously I want to add highlighting, so that when I click on one node the node with the same name in the second and third tree will be highlighted as well. I got this example in jsfiddle and modified to look the same as my issue. Now for example when I hover over the node that has the name Son of A I want this node with this name to be highlighted in the second and third tree as well. Thank you for your help!

lemming

I have edited your fiddle to show how to render the trees with a single function, and implemented the highlighting: https://jsfiddle.net/j2mhokbz/1/

With regards to creating a single function, you have identified what is changing... the data object from the array. So simply add that as a parameter of the draw function and pass in the slice of the data that you want. Note the new data parameter, and the fact that this is passed to the update function.

draw('#svg1', treeData[0]);
draw('#svg2', treeData[1]);
draw('#svg3', treeData[2]);

function draw(selector, data) {
  ...
  update(data);

  function update(dataForUpdate) {
    ...
    var nodes = tree.nodes(dataForUpdate).reverse(),
    ...
  }
}

For the highlighting, the basic principle is to add a highlighted class to the circle and a new css rule that defines how the circle should look when it has a highlighted class.

On mouseover, you select the sibling text element of a circle by first selecting the circle's parent node (a g element) and then selecting that node's child text element.

Then extract the text from the text element and use the filter method to only return elements that are bound to data with the same name. Then add the highlighted class.

On mouseout, the same procedure is used except that an empty string set as the class, which removes the highlighting.

As it is basically the same procedure, you can create a single function to set or unset the highlighted class for nodes with the same name. See the code below:

d3.selectAll('circle')
  .on('mouseover', function() {
    setHighlightedForSimilarNodes(this, true);
  })
  .on('mouseout', function() {
    setHighlightedForSimilarNodes(this, false);
  });

function setHighlightedForSimilarNodes(node, isHighlighted) {
  const text = d3.select(node.parentNode).select('text').text();
  d3.selectAll('circle').filter((d, i) => {
    return d.name === text;
  })
  .attr('class', isHighlighted ? 'highlighted' : '');
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How do you highlight nodes, their connected nodes, and their connections when moused over in d3?

How to highlight multiple rows when hovering over one row

how to make one function instead of 3 functions?

How to highlight a whole cell when hovering over link

How to highlight the whole button when hovering over CSS Grid item?

networkD3 package: show node names of all connected nodes when hovering over

Is there a way to add more information when hovering over a Plotly graph?

d3: hovering over words in text at the same time highlighting the corresponding bars and make word in text clickable

How do add a class to another div, when hovering over one div?

How to add custom colors in D3 nodes of a graph

How to add custom conditional colors in D3 tree nodes?

CSS Highlight Table Row But Not When Hovering First 3 Cells

D3 Tree - How to expand tree to show and highlight all nodes of same name?

How to make labels appear when hovering over a point in multiple axis?

how to make color change to white when hovering over button

When hovering over li, how to make give the a a tag underline

How to make a tolltip appear only when hovering over text?

How to make the border appear when hovering over a button in Kivy

How to change css of one class when hovering over another?

How to change the style of other elements when hovering over one of them?

How to make TTreeView not highlight all nodes when disabled?

In a network graph, how do I highlight the network components when hovering over them?

CSS3 Slight indentation when hovering over a nav item

How to simulate mouse move in D3 so when you drag nodes, other nodes move automatically?

How to make button highlight when hovered over using a template

How do you customize the d3 link strength as a function of the links and nodes counts ? (d3 v4)

How to add a key to a networkD3 visualization

How to stick the dragged nodes in D3

How can I highlight a part of a grouped chart when filter d3

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive