D3: Hyperlinks in a tree structure

I am having trouble hyperlinking children in a graph of a Reingold-Tifold tree. The graph is built in D3 and is based on the fact that Mike Bostock uses an example: http://bl.ocks.org/mbostock/4339184

My code and segment of my JSON file are below.

At this point, the graph works fine - if I click on the parent node, it expands to show a series of child nodes that are contained in my JSON file. But when I get to the level of a child, I want to make the word a hyperlink. I don’t understand how to do this.

I used the previous SO question / answer - Hyperlinks in d3.js objects - to figure out how to add a URL to my JSON data (for now, everything is just related to Google.co.uk). But I don’t understand how to associate this URL with my tree so that the child nodes become hyperlinks.

Can you tell me how I can do this?

Thanks for any help. (And thanks, @ IH8, for your help so far.)

Matt

<html xmlns:xlink="http://www.w3.org/1999/xlink"> <head><meta charset="utf-8"> <style> .node { cursor: pointer; } .node circle { fill: #FF0000; stroke: black; stroke-width: 1.5px; } .node text { font: 11px sans-serif; } .link { fill: none; stroke: #FF0000; stroke-width: 1.5px; } </style> <style id="style-1-cropbar-clipper">/* Copyright 2014 Evernote Corporation. All rights reserved. */ .en-markup-crop-options { top: 18px !important; left: 50% !important; margin-left: -100px !important; width: 200px !important; border: 2px rgba(255,255,255,.38) solid !important; border-radius: 4px !important; } .en-markup-crop-options div div:first-of-type { margin-left: 0px !important; } </style></head><body> <script src="http://d3js.org/d3.v3.min.js"></script> <script> var margin = {top: 20, right: 120, bottom: 20, left: 120}, width = 960 - margin.right - margin.left, height = 800 - margin.top - margin.bottom; var i = 0, duration = 750, root; var tree = d3.layout.tree() .size([height, width]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [dy, dx]; }); var svg = d3.select("body").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 + ")"); d3.json("/sites/default/files/tcs/D3/data/turbo.json", function(error, turbo) { root = turbo; root.x0 = height / 2; root.y0 = 0; function collapse(d) { if (d.children) { d._children = d.children; d._children.forEach(collapse); d.children = null; } } root.children.forEach(collapse); update(root); }); d3.select(self.frameElement).style("height", "800px"); 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) { dy = d.depth * 180; }); // Update the nodes… var node = svg.selectAll("g.node") .data(nodes, function(d) { return d.id || (d.id = ++i); }); // Enter any new nodes at the parent previous position. var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) .on("click", click); nodeEnter.append("circle") .attr("r", 1e-6) .style("fill", function(d) { return d._children ? "red" : "#fff"; }); nodeEnter.each(function(d){ var thisNode = d3.select(this); if (!d.children) { thisNode.append("a") .attr("xlink:href", function(d) { return d.url; }) .append("text") .attr("x", 8) .attr("dy", 3) .attr("text-anchor", "start") .text(function(d) { return d.name; }); } else { thisNode.append("text") .attr("x", -8) .attr("dy", 3) .attr("text-anchor", "end") .text(function(d) { return d.name; }); } }); // Transition nodes to their new position. var nodeUpdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); nodeUpdate.select("circle") .attr("r", 4.5) .style("fill", function(d) { return d._children ? "red" : "#fff"; }); nodeUpdate.select("text") .style("fill-opacity", 1); // Transition exiting nodes to the parent new position. var nodeExit = node.exit().transition() .duration(duration) .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) .remove(); nodeExit.select("circle") .attr("r", 1e-6); nodeExit.select("text") .style("fill-opacity", 1e-6); // Update the links… var link = svg.selectAll("path.link") .data(links, function(d) { return d.target.id; }); // Enter any new links at the parent previous position. link.enter().insert("path", "g") .attr("class", "link") .attr("d", function(d) { var o = {x: source.x0, y: source.y0}; return diagonal({source: o, target: o}); }); // Transition links to their new position. link.transition() .duration(duration) .attr("d", diagonal); // Transition exiting nodes to the parent new position. link.exit().transition() .duration(duration) .attr("d", function(d) { var o = {x: source.x, y: source.y}; return diagonal({source: o, target: o}); }) .remove(); // Stash the old positions for transition. nodes.forEach(function(d) { d.x0 = dx; d.y0 = dy; }); } // Toggle children on click. function click(d) { if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(d); } </script> </body> </html> 

Part of my JSON file:

 { "name": "turbo", "children": [ { "name": "Level 1", "children": [ { "name": "Google", "children": [ {"name": "Website", "size": 3938, "URL":"http://www.google.co.uk"}, {"name": "CommunityStructure", "size": 3812, "URL":"http://www.google.co.uk"}, {"name": "HierarchicalCluster", "size": 6714, "URL":"http://www.google.co.uk"}, {"name": "MergeEdge", "size": 743, "URL":"http://www.google.co.uk"} ] }, { "name": "graph", "children": [ {"name": "BetweennessCentrality", "size": 3534, "URL":"http://www.google.co.uk"}, {"name": "LinkDistance", "size": 5731, "URL":"http://www.google.co.uk"}, {"name": "MaxFlowMinCut", "size": 7840, "URL":"http://www.google.co.uk"}, {"name": "ShortestPaths", "size": 5914, "URL":"http://www.google.co.uk"}, {"name": "SpanningTree", "size": 3416, "URL":"http://www.google.co.uk"} ] }, { "name": "optimization", "children": [ {"name": "AspectRatioBanker", "size": 7074, "URL":"http://www.google.co.uk"} ] } ] }, . . . 
+2
source share
1 answer

It seems you made a small mistake when creating the url attribute of the dataset, or you need to adapt the code you use to add the xlink: href attribute to the element. You are calling:

 .attr("xlink:href", function(d) { return d.url; }) 

But in your dataset, an attribute is defined as follows:

 "URL": "http://www.google.co.uk" 

Those that do not match, you should change your code to this:

 .attr("xlink:href", function(d) { return d.url; }) 

Or your dataset for this:

  "url": "http://www.google.co.uk" 

Remember that JSON property names are case sensitive.

+4
source

Source: https://habr.com/ru/post/979747/


All Articles