d3js Making last circle a hyperlink
Asked Answered
C

2

6

Okay... I am using the Zoomable Circle Packing from http://bl.ocks.org/mbostock/7607535 I opened the flare.json file and started messing with it and was able to manipulate it successfully. It looks like this:

flare.json

{
  "name": "flare",
"children": [
{
"name": "Kommunikation und Umwelt",
"children": [

{
 "name": "Courses",
 "children": [
  {
   "name": "AO-Psy.",
   "children": [
    {"name": "Prof. A", "size": 5731,"url":"google.com"},
    {"name": "Prof. B", "size": 5731},
    {"name": "Prof. C", "size": 5731}
   ]
  },
  {
   "name": "E&E",
   "children": [
    {"name": "Prof. D", "size": 5731},
    {"name": "Prof. E", "size": 5731},
    {"name": "Prof. F", "size": 5731},
    {"name": "Prof. G", "size": 5731},
    {"name": "Prof. H", "size": 5731}
   ]
  },
  {
   "name": "IBSS",
   "children": [
    {"name": "Prof. I", "size": 5731},
    {"name": "Prof. J", "size": 5731},
    {"name": "Prof. K", "size": 5731}
   ]
  },
  {"name": "", "size": 0},
  {
   "name": "E-Gov",
   "children": [
    {"name": "Prof. L", "size": 5731},
    {"name": "Prof. M", "size": 5731},
    {"name": "Prof. N", "size": 5731}
   ]
  },
  {
   "name": "Muki",
   "children": [
    {"name": "Prof. O", "size": 5731},
    {"name": "Prof. P", "size": 5731},
    {"name": "Prof. Q", "size": 5731},
    {"name": "Prof. V", "size": 5731}
   ]
  },
  {"name": "Schedule", "size": 5731},
  {"name": "News", "size": 5731},
  {"name": "Events", "size": 5731},
  {"name": "Search", "size": 5731},
  {"name": "", "size": 0}
 ]
},
{"name": "", "size": 0}
]

},

What I want to do now, is to try to add hyperlinks. For example, I want to be able to click on "ProfA" and go to another html page i will creat. Is there a modification I can make to flare.json that will do that?

i already found some postsPost1 Post2 Post3
but nothing is working it just zoom out again

here complete html file, flare.json is already posted here(short part)
zoom.html:

<html xmlns:xlink="http://www.w3.org/1999/xlink">
<meta charset="utf-8">
<style>

.node {
cursor: pointer;
}

.node:hover {
stroke: #000;
stroke-width: 1.5px;
}

.node--leaf {
fill: #14DCD2;
}

.label {
 font: 20px "Helvetica Neue", Helvetica, Arial, sans-serif;
 text-anchor: middle;
 text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
 }

 .label,
 .node--root,
 .node--leaf {
 pointer-events: none;
 }

 </style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
 <script>


var margin = 600,
diameter = 1920;

var color = d3.scale.linear()
.domain([-1, 5])
.range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl);

var pack = d3.layout.pack()
.padding(2)
.size([diameter - margin, diameter - margin])
.value(function(d) { return d.size; })

var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");

d3.json("flare.json", function(error, root) {
if (error) return console.error(error);

var focus = root,
  nodes = pack.nodes(root),
  view;

var circle = svg.selectAll("circle")
  .data(nodes)
.enter().append("circle")
  .attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
  .style("fill", function(d) { return d.children ? color(d.depth) : null; })
  .on("click", function(d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); })



  var text = svg.selectAll("text")
  .data(nodes)
 .enter().append("text")
  .attr("class", "label")
  .style("fill-opacity", function(d) { return d.parent === root ? 1 : 0; })
  .style("display", function(d) { return d.parent === root ? null : "none"; })
  .text(function(d) { return d.name; })
  //.on('click', function(d, i) {window.location.href = d.url;});

  var node = svg.selectAll("circle,text")

  node.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("dx", 8)
            .attr("dy", 3)
            .attr("text-anchor", "start")
            .text(function(d) { return d.name; })
            ;
   } else {
    thisNode.append("text")
        .attr("dx", -8)
        .attr("dy", 3)
        .attr("text-anchor", "end")
        .text(function(d) { return d.name; });      
     }

    });




   d3.select("body")
  .style("background", color(-1))
  .on("dblclick", function() { zoom(root); });

   zoomTo([root.x, root.y, root.r * 2 + margin]);

   function zoom(d) {
   var focus0 = focus; focus = d;
   //.attr("xlink:href", url);
   //.on('click', function(d, i) {window.location.href = d.url;});

   var transition = d3.transition()
    .duration(d3.event.altKey ? 7500 : 750)
    .tween("zoom", function(d) {
      var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 4 + margin]);
      return function(t) { zoomTo(i(t)); };
    });

    transition.selectAll("text")
   .filter(function(d) { return d.parent === focus || this.style.display === "inline"; })
    .style("fill-opacity", function(d) { return d.parent === focus ? 1 : 0; })
    .each("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
    .each("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });

    }

    function zoomTo(v) {
    var k = diameter / v[2]; view = v;
    node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
    circle.attr("r", function(d) { return d.r * k; });

    }

     });

     d3.select(self.frameElement).style("height", diameter + "px");

    </script>
    </html>
Connaught answered 16/12, 2014 at 21:38 Comment(0)
D
7

The problem in your setup mostly stems from the fact that you have pointer-events: none for certain elements, such as the leaves (smallest circles).

If you correct that and define the click event such that it directs to the url instead of triggering a zoom event for the leaves, you get the desired behavior.

I put together a small fiddle for you, see here: http://jsfiddle.net/chroth/fkxcvtu9/3/

The core of the idea is in here (click function):

function clickFct(d,i) {
if (d3.select(this).classed("node--leaf")) {
    alert(d.url); //open URL here
} else {
    if (focus !== d) 
    {
        zoom(d); 
        d3.event.stopPropagation();
    }
}
}

and in this change in the style:

 .node--root,
 .node--leaf {
   pointer-events: all;
 }

TODOs

As you can see, currently I am just shooting an alert. Also, you might want to disable certain click events when not zoomed in etc. Plus work on the colors.

Also, note that you need to fix the visibility of the labels etc.

But I leave that to you :)

Hope that helps.

Defroster answered 16/12, 2014 at 21:45 Comment(5)
its working omg i am so happy right now you saved me man thank you so muchConnaught
you're welcome! please be aware that my answer is just the start - see the todos! good luck!Defroster
yeah i´ll keep working on it. Is it okay to ask more question if i dont make any progress?Connaught
I think stackoverflow has no question limit :) (as long as you show effort :))Defroster
hay man can you help me with the click events because i cant find an answer? i got an answer from somebody but i cant figure out how to do this i really hope you can help me #27948812Connaught
E
1

Thanks Pinguin. It is working correctly for me, but I am not sure about the purpose for the i parameter in your function. Here is a small modification that protects against urls that are undefined.

function onClickLeaf(d) 
{
    if (d3.select(this).classed("node--leaf")) 
    {
        if(d.url !== undefined)
        {
            alert(d.url); //open URL here
        }
    } 
    else 
    {
        if (focus !== d) 
        {
            zoom(d); 
            d3.event.stopPropagation();
        }
    }
}

Up vote from me due to this particular line of code, and being nice enough to wrap it into a function for simplicity.

if (d3.select(this).classed("node--leaf")) 
Epigrammatist answered 3/2, 2015 at 8:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.