Related
I am trying to implement paging in d3 tree. Can anyone please help me with the same.
Please find below my code with screenshots of current and expected output.
The data_tree is the input data variable. This gets read by script below and produces hierarchy tree as showed in screenshot
data_tree = {
"Type": "Root",
"id": 0,
"name": "ERM",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 4,
"name": "RG",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 5,
"name": "WCR F",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Stem",
"id": 50,
"name": "WCR P",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Leaf",
"id": 8,
"name": "IBQA SD",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 9,
"name": "WCR EMS",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 28,
"name": "WCR DD & RGEC",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 29,
"name": "PMM",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 30,
"name": "PRRM",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 31,
"name": "WCR Rep",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 32,
"name": "RR",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 33,
"name": "CO",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 34,
"name": "LD",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 35,
"name": "ESRM",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 36,
"name": "TPCR",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 37,
"name": "InterA",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 38,
"name": "DR",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 39,
"name": "MAR",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 40,
"name": "BSLM",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 51,
"name": "CCR Meas",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 52,
"name": "WLP",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 53,
"name": "TTS Pro",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 54,
"name": "CI",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 55,
"name": "LL",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 56,
"name": "SP",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 57,
"name": "CC",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 58,
"name": "CRE",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 59,
"name": "Sec",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
},
{
"Type": "Leaf",
"id": 60,
"name": "SS",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
}
]
}]
},
{
"Type": "Stem",
"id": 10,
"name": "GCMP",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Leaf",
"id": 11,
"name": "WCR CMS",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
}]
},
{
"Type": "Stem",
"id": 12,
"name": "REAVP",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 13,
"name": "CREAVS",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Leaf",
"id": 14,
"name": "CREAVP",
"ParentDocType": "WholesaleCreditRisk",
"children": [
]
}]
}]
}
]
}]
};
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 960 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var root =JSON.parse(data_tree);
var i = 0,
duration = 750,
rectW = 150,
rectH = 50;
//var tree = d3.layout.tree().nodeSize([70, 40]);
var nodeWidth = 150;
var nodeHeight = 50;
var horizontalSeparationBetweenNodes = 16;
var verticalSeparationBetweenNodes = 128;
var tree = d3.layout.tree()
.nodeSize([nodeWidth + horizontalSeparationBetweenNodes, nodeHeight + verticalSeparationBetweenNodes])
.separation(function(a, b) {
return a.parent == b.parent ? 1 : 1.25;
});
/*var diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.x + rectW / 2, d.y + rectH / 6];
});*/
var diagonal = d3.svg.diagonal()
.target(function(d) {
var o = d.target;
o.y = o.y - 50
return o;
})
.projection(function(d) {
return [d.x + rectW / 2, d.y + rectH];
});
var svg = d3.select("#body").append("svg").attr("width", document.getElementById("body").style.width).attr("height", document.getElementById("body").style.height)
.call(zm = d3.behavior.zoom().scaleExtent([0.5, 3]).on("zoom", redraw)).append("g")
.attr("transform", "translate(" + 650 + "," + 20 + ")scale(0.7)");
//necessary so that zoom knows where to zoom and unzoom from
zm.translate([650, 20]);
root.x0 = 0;
root.y0 = height / 2;
d3.select("#myCheckbox").on("change", enableLink);
enableLink(root);
d3.select("#body").style("height", "800px");
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
}
function enableLink(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 * 125;
});
// 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's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.x0 + "," + source.y0 + ")";
}).on("click", click);
nodeEnter.append("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "blue")
.attr("rx", 4)
.attr("ry", 4)
.attr("stroke-width", 2)
.style("fill", function(d) {
if (d.ParentDocType == "EnterpriseWide") return "darkblue";
if (d.ParentDocType == "WholesaleCreditRisk") return "blue";
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", rectW / 2)
.attr("y", rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
}).call(wrap, rectW - 10);
nodeEnter
.append("a")
.attr("xlink:href", function(d) {
return d.url;
});
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
nodeUpdate.select("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "blue")
.attr("stroke-width", 2)
.style("fill", function(d) {
if (d.ParentDocType == "EnterpriseWide") return "darkblue";
if (d.ParentDocType == "WholesaleCreditRisk") return "blue";
return d._children ? "lightsteelblue" : "#fff";
});
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.x + "," + source.y + ")";
})
.remove();
nodeExit.select("rect")
.attr("width", rectW)
.attr("height", rectH)
//.attr("width", bbox.getBBox().width)""
//.attr("height", bbox.getBBox().height)
.attr("stroke", "blue")
.attr("stroke-width", 2);
nodeExit.select("text");
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
d.y = d.y + 100;
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0 + 100
};
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's 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 = d.x;
d.y0 = d.y + 100;
});
}
// 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;
}
enableLink(d);
}
//Redraw for zoom
function redraw() {
//console.log("here", d3.event.translate, d3.event.scale);
svg.attr("transform",
"translate(" + d3.event.translate + ")" +
" scale(" + d3.event.scale + ")");
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
fill: white;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
body {
overflow: hidden;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.box {
float: left;
height: 20px;
width: 20px;
margin-bottom: 15px;
border: 1px solid black;
}
.darkblue {
background-color: darkblue;
}
.blue {
background-color: blue;
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
</head>
<body>
<div id="body" style="border: 1px black solid; width:100%; height:600px;"></div>
</body>
Current output
Expected output
var root = {
"Type": "Root",
"id": 0,
"name": "ERM",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 4,
"name": "RG",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 5,
"name": "WCR F",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Stem",
"id": 50,
"name": "WCR P",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Leaf",
"id": 8,
"name": "IBQA SD",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 9,
"name": "WCR EMS",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 28,
"name": "WCR DD & RGEC",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 29,
"name": "PMM",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 30,
"name": "PRRM",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 31,
"name": "WCR Rep",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 32,
"name": "RR",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 33,
"name": "CO",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 34,
"name": "LD",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 35,
"name": "ESRM",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 36,
"name": "TPCR",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 37,
"name": "InterA",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 38,
"name": "DR",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 39,
"name": "MAR",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 40,
"name": "BSLM",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 51,
"name": "CCR Meas",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 52,
"name": "WLP",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 53,
"name": "TTS Pro",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 54,
"name": "CI",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 55,
"name": "LL",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 56,
"name": "SP",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 57,
"name": "CC",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 58,
"name": "CRE",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 59,
"name": "Sec",
"ParentDocType": "WholesaleCreditRisk",
"children": []
},
{
"Type": "Leaf",
"id": 60,
"name": "SS",
"ParentDocType": "WholesaleCreditRisk",
"children": []
}
]
}]
},
{
"Type": "Stem",
"id": 10,
"name": "GCMP",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Leaf",
"id": 11,
"name": "WCR CMS",
"ParentDocType": "WholesaleCreditRisk",
"children": []
}]
},
{
"Type": "Stem",
"id": 12,
"name": "REAVP",
"ParentDocType": "EnterpriseWide",
"children": [{
"Type": "Stem",
"id": 13,
"name": "CREAVS",
"ParentDocType": "WholesaleCreditRisk",
"children": [{
"Type": "Leaf",
"id": 14,
"name": "CREAVP",
"ParentDocType": "WholesaleCreditRisk",
"children": []
}]
}]
}
]
}]
};
function pageNodes(d) {
if (d.children) {
d.children.forEach(c => pageNodes(c));
if (d.children.length > pageNodes.maxNode) {
d.pages = {}
const count = pageNodes.maxNode - 1;
const l = Math.ceil(d.children.length / count);
for (let i = 0; i < l; i++) {
let startRange = i * count;
let endRange = i * count + count;
d.pages[i] = d.children.slice(startRange, endRange);
pageNodes.addNode(d.pages[i], "More...", {
__next: i != (l - 1) ? i + 1 : 0,
});
}
d.children = d.pages[0];
}
}
}
pageNodes.maxNode = 5;
pageNodes.addNode = function(children, name, more) {
let node = Object.assign({
Type: "Leaf",
id: children[children.length - 1].id + 10000,
ParentDocType: children[children.length - 1].ParentDocType,
name: name,
}, more);
children.push(node);
};
root.children.forEach(c => pageNodes(c));
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = window.innerWidth - margin.right - margin.left,
height = window.innerHeight - margin.top - margin.bottom;
var i = 0,
duration = 750,
rectW = 150,
rectH = 50;
// var tree = d3.layout.tree().nodeSize([70, 40]);
var nodeWidth = 150;
var nodeHeight = 50;
var horizontalSeparationBetweenNodes = 16;
var verticalSeparationBetweenNodes = 128;
var tree = d3.layout.tree()
.nodeSize([nodeWidth + horizontalSeparationBetweenNodes, nodeHeight + verticalSeparationBetweenNodes])
.separation(function(a, b) {
return a.parent == b.parent ? 1 : 1.25;
});
/*var diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.x + rectW / 2, d.y + rectH / 6];
});*/
var diagonal = d3.svg.diagonal()
.target(function(d) {
var o = d.target;
o.y = o.y - 50
return o;
})
.projection(function(d) {
return [d.x + rectW / 2, d.y + rectH];
});
var svg = d3.select("#body").append("svg").attr("width", document.getElementById("body").style.width).attr("height", document.getElementById("body").style.height)
.call(zm = d3.behavior.zoom().scaleExtent([0.5, 3]).on("zoom", redraw)).append("g")
.attr("transform", "translate(" + 650 + "," + 20 + ")scale(0.7)");
//necessary so that zoom knows where to zoom and unzoom from
zm.translate([650, 20]);
root.x0 = 0;
root.y0 = height / 2;
d3.select("#myCheckbox").on("change", enableLink);
enableLink(root);
d3.select("#body").style("height", "800px");
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
}
function enableLink(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 * 125;
});
// 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's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.x0 + "," + source.y0 + ")";
}).on("click", click);
nodeEnter.append("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "blue")
.attr("rx", 4)
.attr("ry", 4)
.attr("stroke-width", 2)
.style("fill", function(d) {
if (d.ParentDocType == "EnterpriseWide") return "darkblue";
if (d.ParentDocType == "WholesaleCreditRisk") return "blue";
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", rectW / 2)
.attr("y", rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
}).call(wrap, rectW - 10);
nodeEnter
.append("a")
.attr("xlink:href", function(d) {
return d.url;
});
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
nodeUpdate.select("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "blue")
.attr("stroke-width", 2)
.style("fill", function(d) {
if (d.ParentDocType == "EnterpriseWide") return "darkblue";
if (d.ParentDocType == "WholesaleCreditRisk") return "blue";
return d._children ? "lightsteelblue" : "#fff";
});
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.x + "," + source.y + ")";
})
.remove();
nodeExit.select("rect")
.attr("width", rectW)
.attr("height", rectH)
//.attr("width", bbox.getBBox().width)""
//.attr("height", bbox.getBBox().height)
.attr("stroke", "blue")
.attr("stroke-width", 2);
nodeExit.select("text");
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
d.y = d.y + 100;
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0 + 100
};
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's 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 = d.x;
d.y0 = d.y + 100;
});
}
// Toggle children on click.
function click(d) {
if (d.hasOwnProperty('__next')) {
d.parent.children = d.parent.pages[d.__next];
} else if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
enableLink(d);
}
//Redraw for zoom
function redraw() {
//console.log("here", d3.event.translate, d3.event.scale);
svg.attr("transform",
"translate(" + d3.event.translate + ")" +
" scale(" + d3.event.scale + ")");
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
fill: white;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
body {
overflow: hidden;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.box {
float: left;
height: 20px;
width: 20px;
margin-bottom: 15px;
border: 1px solid black;
}
.darkblue {
background-color: darkblue;
}
.blue {
background-color: blue;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<div id="body" style="border: 1px black solid; width:100%; height:600px;"></div>
I want to highlight the selected node and its connected nodes on clicking any node in d3js,
and the other nodes will disappear or gets dull.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="D3js_edges_connected_by_nodes_id.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<title>Weighted Citation Graph</title>
<style>
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
text.shadow {
stroke: #fff;
stroke-width: 3px;
stroke-opacity: .8;
}
body {
background-color: white;
margin: 0px;
}
.graphContainer {
text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
}
</style>
<script>
function load_graph(text) {
var color = d3.scale.category20();
//try{
// var data = JSON.parse(text);
//} catch (e) {
// window.alert("sometext: "+e);
//}
var data = { "nodes": [{ "id": 127230, "name": "Optimization of query evaluation algorithms", "citation": 26, "group": 10 }, { "id": 127254, "name": "Flow algorithms for parallel query optimization", "citation": 22, "group": 10 }, { "id": 127380, "name": "Randomized approximation algorithms for query optimization problems on two processors", "citation": 14, "group": 10 }, { "id": 127438, "name": "Optimization algorithms for simultaneous multidimensional queries in OLAP environments", "citation": 12, "group": 10 }, { "id": 127063, "name": "Query optimization in database systems", "citation": 230, "group": 10 }, { "id": 127158, "name": "Query optimization in a memory-resident domain relational calculus database system", "citation": 41, "group": 10 }, { "id": 129760, "name": "An Overview of TQuel", "citation": 22, "group": 10 }, { "id": 129867, "name": "ADVISORS", "citation": 10, "group": 10 }, { "id": 129872, "name": "Tellabs and THRIP through the Telkom Centre of Excellence at Rhodes University.", "citation": 10, "group": 10 }, { "id": 127412, "name": "Optimal service ordering in decentralized queries over web services", "citation": 13, "group": 10 }, { "id": 130856, "name": "Queries over Web Services", "citation": 10, "group": 10 }, { "id": 130959, "name": "Exploiting Parallelism to Accelerate Keyword Search On Deep-web Sources", "citation": 10, "group": 10 }, { "id": 131199, "name": "Contents lists available at ScienceDirect Future Generation Computer Systems", "citation": 10, "group": 10 }, { "id": 131211, "name": "Flow Algorithms for Parallel Query Optimization", "citation": 10, "group": 10 }, { "id": 127373, "name": "Multi-query Optimization for On-Line Analytical Processing", "citation": 14, "group": 10 }, { "id": 133379, "name": "Concise descriptions of subsets of structured sets", "citation": 21, "group": 10 }], "links": [{ "source": 127230, "target": 127063, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127230, "target": 127158, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127230, "target": 129760, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127230, "target": 129867, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127230, "target": 129872, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127230, "target": 127063, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127230, "target": 127158, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127230, "target": 129760, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127230, "target": 129867, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127230, "target": 129872, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127254, "target": 127412, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127254, "target": 130856, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127254, "target": 130959, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127254, "target": 131199, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127254, "target": 131211, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127254, "target": 127412, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127254, "target": 130856, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127254, "target": 130959, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127254, "target": 131199, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127254, "target": 131211, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127438, "target": 127373, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127438, "target": 133379, "name": "c1", "value": 10, "grouo": 1 }, { "source": 127438, "target": 127373, "name": "c1", "value": 10, "grouo": 9 }, { "source": 127438, "target": 133379, "name": "c1", "value": 10, "grouo": 9 }] };
// used to store the number of links between two nodes.
// mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
var mLinkNum = {};
// sort links first
// sortLinks();
data.links.sort(function (a, b) {
if (a.source > b.source) { return 1; }
else if (a.source < b.source) { return -1; }
else {
if (a.target > b.target) { return 1; }
if (a.target < b.target) { return -1; }
else { return 0; }
}
})
// set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
setLinkIndexAndNum();
var w = 1345,
h = 1000;
var force = d3.layout.force()
.size([w, h])
.linkDistance(100)
.charge(-800)
.on("tick", tick);
var svg = d3.select(".graphContainer").append("svg:svg")
.attr("width", w)
.attr("height", h);
var color = d3.scale.category10()
var edges = [];
data.links.forEach(function (e) {
var sourceNode = data.nodes.filter(function (n) {
return n.id === e.source;
})[0],
targetNode = data.nodes.filter(function (n) {
return n.id === e.target;
})[0];
edges.push({
source: sourceNode,
target: targetNode,
name: e.name,
value: e.value,
linkindex: e.linkindex,
grouo: e.grouo
});
});
console.log(edges)
force
.nodes(data.nodes)
.links(edges)
.start();
var path = svg.append("svg:g")
.selectAll("line")
.data(edges)
.enter().append("svg:path")
.attr("class", "link")
.style("stroke-width", function (d, i) {
console.log(d.value)
return Math.sqrt(d.value);
}).style('stroke', function (d) {
return color(d.grouo);
});
var circle = svg.append("svg:g")
.selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", function (d) {
return (Math.sqrt(d.citation));
})
.style("fill", function (d) {
return color(d.group);
})
.call(force.drag);
var text = svg.append("svg:g")
.selectAll("g")
.data(force.nodes())
.enter().append("svg:g");
console.log('test');
// A copy of the text with a thick white stroke for legibility.
//text.append("svg:text")
//.attr("x", 8)
//.attr("y", ".31em")
//.attr("class", "shadow")
//.text(function (d) {
//return d.name;
//});
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.text(function (d) {
// return d.name;
});
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
path.attr("d", function (d, i) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = 30 * d.linkindex; //linknum is defined above
var output = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
//console.log(d)
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
// Add tooltip to the connection path
path.append("svg:title")
.text(function (d, i) {
return d.name;
});
circle.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
// sort the links by source, then target
function sortLinks1() {
data.links.sort(function (a, b) {
if (a.source > b.source) {
return 1;
} else if (a.source < b.source) {
return -1;
} else {
if (a.target > b.target) {
return 1;
}
if (a.target < b.target) {
return -1;
} else {
return 0;
}
}
});
}
//any links with duplicate source and target get an incremented 'linknum'
function setLinkIndexAndNum1() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
console.log(data.links[i].linkindex)
} else {
data.links[i].linkindex = 1;
console.log(data.links[i].linkindex)
}
// save the total number of links between two nodes
if (mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined) {
mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
} else {
mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
}
}
}
function setLinkIndexAndNum() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
}
else {
data.links[i].linkindex = 1;
};
};
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<script src="//d3js.org/d3.v3.min.js"></script>
<%--<textarea runat="server" id="textarea" cols="80" rows="20"></textarea>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>--%>
</div>
<div id="graphContainer" class="graphContainer"></div>
</form>
</body>
</html>
is there any way of applying this kind of functionality in d3js?
There are several ways to make it. This is one of them:
circle.on("click", function(d) {
var thisNode = d.id
var connected = data.links.filter(function(e) {
return e.source === thisNode || e.target === thisNode
});
circle.attr("opacity", function(d) {
return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
});
path.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
});
Check the demo with your code:
var color = d3.scale.category20();
//try{
// var data = JSON.parse(text);
//} catch (e) {
// window.alert("sometext: "+e);
//}
var data = {
"nodes": [{
"id": 127230,
"name": "Optimization of query evaluation algorithms",
"citation": 26,
"group": 10
}, {
"id": 127254,
"name": "Flow algorithms for parallel query optimization",
"citation": 22,
"group": 10
}, {
"id": 127380,
"name": "Randomized approximation algorithms for query optimization problems on two processors",
"citation": 14,
"group": 10
}, {
"id": 127438,
"name": "Optimization algorithms for simultaneous multidimensional queries in OLAP environments",
"citation": 12,
"group": 10
}, {
"id": 127063,
"name": "Query optimization in database systems",
"citation": 230,
"group": 10
}, {
"id": 127158,
"name": "Query optimization in a memory-resident domain relational calculus database system",
"citation": 41,
"group": 10
}, {
"id": 129760,
"name": "An Overview of TQuel",
"citation": 22,
"group": 10
}, {
"id": 129867,
"name": "ADVISORS",
"citation": 10,
"group": 10
}, {
"id": 129872,
"name": "Tellabs and THRIP through the Telkom Centre of Excellence at Rhodes University.",
"citation": 10,
"group": 10
}, {
"id": 127412,
"name": "Optimal service ordering in decentralized queries over web services",
"citation": 13,
"group": 10
}, {
"id": 130856,
"name": "Queries over Web Services",
"citation": 10,
"group": 10
}, {
"id": 130959,
"name": "Exploiting Parallelism to Accelerate Keyword Search On Deep-web Sources",
"citation": 10,
"group": 10
}, {
"id": 131199,
"name": "Contents lists available at ScienceDirect Future Generation Computer Systems",
"citation": 10,
"group": 10
}, {
"id": 131211,
"name": "Flow Algorithms for Parallel Query Optimization",
"citation": 10,
"group": 10
}, {
"id": 127373,
"name": "Multi-query Optimization for On-Line Analytical Processing",
"citation": 14,
"group": 10
}, {
"id": 133379,
"name": "Concise descriptions of subsets of structured sets",
"citation": 21,
"group": 10
}],
"links": [{
"source": 127230,
"target": 127063,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 127158,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129760,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129867,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129872,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 127063,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 127158,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129760,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129867,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129872,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 127412,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 130856,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 130959,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 131199,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 131211,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 127412,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 130856,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 130959,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 131199,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 131211,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127438,
"target": 127373,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127438,
"target": 133379,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127438,
"target": 127373,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127438,
"target": 133379,
"name": "c1",
"value": 10,
"grouo": 9
}]
};
// used to store the number of links between two nodes.
// mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
var mLinkNum = {};
// sort links first
// sortLinks();
data.links.sort(function(a, b) {
if (a.source > b.source) {
return 1;
} else if (a.source < b.source) {
return -1;
} else {
if (a.target > b.target) {
return 1;
}
if (a.target < b.target) {
return -1;
} else {
return 0;
}
}
})
// set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
setLinkIndexAndNum();
var w = 1345,
h = 1000;
var force = d3.layout.force()
.size([w, h])
.linkDistance(100)
.charge(-800)
.on("tick", tick);
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
var color = d3.scale.category10()
var edges = [];
data.links.forEach(function(e) {
var sourceNode = data.nodes.filter(function(n) {
return n.id === e.source;
})[0],
targetNode = data.nodes.filter(function(n) {
return n.id === e.target;
})[0];
edges.push({
source: sourceNode,
target: targetNode,
name: e.name,
value: e.value,
linkindex: e.linkindex,
grouo: e.grouo
});
});
force
.nodes(data.nodes)
.links(edges)
.start();
var path = svg.append("svg:g")
.selectAll("line")
.data(edges)
.enter().append("svg:path")
.attr("class", "link")
.style("stroke-width", function(d, i) {
return Math.sqrt(d.value);
}).style('stroke', function(d) {
return color(d.grouo);
});
var circle = svg.append("svg:g")
.selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", function(d) {
return (Math.sqrt(d.citation));
})
.style("fill", function(d) {
return color(d.group);
})
.call(force.drag);
var text = svg.append("svg:g")
.selectAll("g")
.data(force.nodes())
.enter().append("svg:g");
// A copy of the text with a thick white stroke for legibility.
//text.append("svg:text")
//.attr("x", 8)
//.attr("y", ".31em")
//.attr("class", "shadow")
//.text(function (d) {
//return d.name;
//});
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) {
// return d.name;
});
circle.on("click", function(d) {
var thisNode = d.id
var connected = data.links.filter(function(e) {
return e.source === thisNode || e.target === thisNode
});
circle.attr("opacity", function(d) {
return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
});
path.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
});
})
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
path.attr("d", function(d, i) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = 30 * d.linkindex; //linknum is defined above
var output = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
//console.log(d)
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
// Add tooltip to the connection path
path.append("svg:title")
.text(function(d, i) {
return d.name;
});
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
// sort the links by source, then target
function sortLinks1() {
data.links.sort(function(a, b) {
if (a.source > b.source) {
return 1;
} else if (a.source < b.source) {
return -1;
} else {
if (a.target > b.target) {
return 1;
}
if (a.target < b.target) {
return -1;
} else {
return 0;
}
}
});
}
//any links with duplicate source and target get an incremented 'linknum'
function setLinkIndexAndNum1() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
console.log(data.links[i].linkindex)
} else {
data.links[i].linkindex = 1;
}
// save the total number of links between two nodes
if (mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined) {
mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
} else {
mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
}
}
}
function setLinkIndexAndNum() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
} else {
data.links[i].linkindex = 1;
};
};
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
text.shadow {
stroke: #fff;
stroke-width: 3px;
stroke-opacity: .8;
}
body {
background-color: white;
margin: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Small circles with different radius grouped in bigger circles
Here is what I have so far - one circle: http://jsfiddle.net/dmitrychuba/hqy6q6qv/
(function () {
var rand = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
var width = 400,
height = 400,
root = {
"name": "A",
"size": 12323,
"children": [{
"name": "B",
"size": 3938
}, {
"name": "C",
"size": 3812
}, {
"name": "D",
"size": 6714
}, {
"name": "E",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
},
]
};
var force = d3.layout.force()
.linkDistance(function (d) {
return 100;
}) // link distance between the nodes
.charge(-200) // charge that repel nodes from each other
.gravity(0.1)
.size([width, height])
.on("tick", tick);
var svg = d3.select("#main-container").append("svg")
.attr("width", width)
.attr("height", height);
var link = svg.selectAll(".link"),
node = svg.selectAll(".node");
//Fix the position of the nodes and doesnt allow them to move out of the screen
flatten(root); //to set ids
update();
function update() {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force.nodes(nodes)
.links(links)
.start();
// Update nodes.
node = node.data(nodes, function (d) {
return d.id;
});
node.exit().remove();
var nodeEnter = node.enter().append("g")
.attr("class", "node");
//Adjusting the node sizes according to the children
nodeEnter.append("circle")
.style("display", function (d) {
return d.children ? "none" : "";
})
.attr("stroke", 'black')
.attr("r", function (d) {
var r = rand(6, 18);
return d._children ? d.size ? 14 : 18 : d.children ? 24 : r;
});
nodeEnter.append("text")
.attr("dy", ".35em")
.text(function (d) {
return d.name;
}).style("display", function (d) {
return d.children ? "none" : "";
})
.style("font-size", function (d) {
return 10;
});
node.select("circle")
.style("fill", color);
}
function tick() {
link.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
node.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function color(d) {
return "#fd8d3c";
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [],
i = 0;
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!node.id) node.id = ++i;
nodes.push(node);
}
recurse(root);
return nodes;
}
setInterval(function () {
force.alpha(.1);
}, 100);
})();
In order to make several circles I just do 'for' loop here: http://jsfiddle.net/dmitrychuba/hm72c74a/, but this way I have several SVG elements, which is not very good as I can't get them position like on image above(closer to each other). And also I will need few smaller solid circles plus future ability to zoom-in/out.
So my question is: is there a way to have multiple sets of circles on same SVG and with few solid circles and with ability to zoom-in/out?
Thanks
Dmitry
It is better to put all circle groups and individual circles inside a group element rather than putting them as separate SVG. Try as shown below.
var rand = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
var width = 400,
height = 400,
root = {
"name": "A",
"size": 12323,
"children": [{
"name": "B",
"size": 3938
}, {
"name": "C",
"size": 3812
}, {
"name": "D",
"size": 6714
}, {
"name": "E",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
}, {
"name": "D1",
"size": 6714
}, {
"name": "E1",
"size": 743
}, {
"name": "B1",
"size": 3938
}, {
"name": "C1",
"size": 3812
},
]
};
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var color = d3.scale.category10();
var svg = d3.select("#main-container").append("svg")
.attr("width", width * 3)
.attr("height", height * 2)
.call(zoom);
var mainContainer = svg.append("g");
function zoomed() {
mainContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
var positions = [
[0, 0],
[width, 0],
[width * 2, 0],
[width - 200, height],
[width * 2 - 200, height]
];
function addCircle(x, y) {
mainContainer.append("circle")
.style("fill", "#3D91B2")
.attr("cx", x)
.attr("cy", y)
.attr("r", 50);
}
addCircle(width, height - 70);
addCircle(width * 2, height - 70);
for (var i = 0; i < 5; i++)
(function() {
var force = d3.layout.force()
.linkDistance(function(d) {
return 100;
}) // link distance between the nodes
.charge(-200) // charge that repel nodes from each other
.gravity(0.1)
.size([width, height])
.on("tick", tick);
var gContainer = mainContainer.append("g")
.attr("transform", "translate(" + positions[i][0] + "," + positions[i][1] + ")");
var link = gContainer.selectAll(".link"),
node = gContainer.selectAll(".node");
//Fix the position of the nodes and doesnt allow them to move out of the screen
flatten(root); //to set ids
update(i);
function update(colorIdx) {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force.nodes(nodes)
.links(links)
.start();
// Update nodes.
node = node.data(nodes, function(d) {
return d.id;
});
node.exit().remove();
var nodeEnter = node.enter().append("g")
.attr("class", "node");
//Adjusting the node sizes according to the children
nodeEnter.append("circle")
.style("display", function(d) {
return d.children ? "none" : "";
})
.attr("stroke", 'black')
.attr("r", function(d) {
var r = rand(6, 18);
return d._children ? d.size ? 14 : 18 : d.children ? 24 : r;
});
nodeEnter.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.name;
}).style("display", function(d) {
return d.children ? "none" : "";
})
.style("font-size", function(d) {
return 10;
});
node.select("circle")
.style("fill", color(colorIdx));
}
function tick() {
link.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [],
i = 0;
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!node.id) node.id = ++i;
nodes.push(node);
}
recurse(root);
return nodes;
}
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="main-container"></div>
I have this D3 instance. I'm trying nodes to collapse and hide its childrens when click but I'm getting "Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node." when I click one.
Since the error happens on d3.js I'm having a big trouble debugging it.
Here's the code
window.onload=function(){
var width = $(window).width();
height = $(window).height();
var force = d3.layout.force()
.gravity(.2)
.charge(-500)
.size([width, height])
.linkDistance(250);
var svg = d3.select("body").append("svg:svg")
.attr("width", width)
.attr("height", height);
var root = getData();
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
nodes.forEach(function(d, i) {
d.x = width/2 + i;
d.y = height/2 + 100 * d.depth;
});
root.fixed = true;
root.x = width / 2;
root.y = height / 2;
force.nodes(nodes)
.links(links)
.start();
var link = svg.selectAll("line")
.data(links)
.enter()
.insert("svg:line")
.attr("class", "link");
var gnodes = svg.selectAll("circle.node")
.data(nodes)
.enter()
.append('g')
.classed('gnode', true);
var node = gnodes.append("circle")
.attr("class", "node")
.attr('data-name', function(d) { return d.name; })
.attr("r", 25)
.style("fill", '#FFFF44' )
.call(force.drag)
.on("click", click);;
var labels = gnodes.append("text")
.attr("text-anchor", "middle")
.attr('class', 'etiqueta')
.text( function(d) { return d.name; } );
force.on("tick", function(e) {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
/*
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
*/
gnodes.attr("transform", function(d) {
return 'translate(' + [d.x, d.y] + ')';
});
});
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update();
}
function update() {
console.log('updating');
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
// Update the links…
link = svg.selectAll("line.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
// Exit any old links.
link.exit().remove();
// Update the nodes…
node = svg.selectAll("circle.node")
.data(nodes, function(d) { return d.id; })
.style("fill", color);
node.transition()
.attr("r", function(d) { return d.children ? 4.5 : Math.sqrt(d.size) / 10; });
// Enter any new nodes.
node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.children ? 4.5 : Math.sqrt(d.size) / 10; })
.style("fill", color)
.call(force.drag)
.on("click", click);
// Exit any old nodes.
node.exit().remove();
}
function flatten(root) {
var nodes = [];
function recurse(node, depth) {
if (node.children) {
node.children.forEach(function(child) {
recurse(child, depth + 1);
});
}
node.depth = depth;
nodes.push(node);
}
recurse(root, 1);
return nodes;
}
function getData() {
return {
"name": "flare",
"children": [{
"name": "analytics",
"children": [{
"name": "cluster",
"children": [{
"name": "AgglomerativeCluster",
"size": 3938
}, {
"name": "CommunityStructure",
"size": 3812
}, {
"name": "HierarchicalCluster",
"size": 6714
}, {
"name": "MergeEdge",
"size": 743
}]
}, {
"name": "graph",
"children": [{
"name": "BetweennessCentrality",
"size": 3534
}, {
"name": "LinkDistance",
"size": 5731
}, {
"name": "MaxFlowMinCut",
"size": 7840
}, {
"name": "ShortestPaths",
"size": 5914
}, {
"name": "SpanningTree",
"size": 3416
}]
}, {
"name": "optimization",
"children": [{
"name": "AspectRatioBanker",
"size": 7074
}]
}]
}, {
"name": "animate",
"children": [{
"name": "interpolate",
"children": [{
"name": "ArrayInterpolator",
"size": 1983
}, {
"name": "ColorInterpolator",
"size": 2047
}, {
"name": "DateInterpolator",
"size": 1375
}, {
"name": "Interpolator",
"size": 8746
}, {
"name": "MatrixInterpolator",
"size": 2202
}, {
"name": "NumberInterpolator",
"size": 1382
}, {
"name": "ObjectInterpolator",
"size": 1629
}, {
"name": "PointInterpolator",
"size": 1675
}, {
"name": "RectangleInterpolator",
"size": 2042
}]
}, {
"name": "ISchedulable",
"size": 1041
}, {
"name": "Parallel",
"size": 5176
}, {
"name": "Pause",
"size": 449
}, {
"name": "Scheduler",
"size": 5593
}, {
"name": "Sequence",
"size": 5534
}, {
"name": "Transition",
"size": 9201
}, {
"name": "Transitioner",
"size": 19975
}, {
"name": "TransitionEvent",
"size": 1116
}, {
"name": "Tween",
"size": 6006
}]
}, {
"name": "data",
"children": [{
"name": "converters",
"children": [{
"name": "Converters",
"size": 721
}, {
"name": "DelimitedTextConverter",
"size": 4294
}, {
"name": "GraphMLConverter",
"size": 9800
}, {
"name": "IDataConverter",
"size": 1314
}, {
"name": "JSONConverter",
"size": 2220
}]
}, {
"name": "DataField",
"size": 1759
}, {
"name": "DataSchema",
"size": 2165
}, {
"name": "DataSet",
"size": 586
}, {
"name": "DataSource",
"size": 3331
}, {
"name": "DataTable",
"size": 772
}, {
"name": "DataUtil",
"size": 3322
}]
}]
};
}
}
I have created simple d3.js bubble chart with heat colors(asp.net page), while opening firefox browser is not working. i got error classes is not defined. In body D3.js is referenced. please let me how to resolve the issue.
Note: The same page is working in Chrome/IE/Safari browser. Only firefox is not working.
source code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
.d3-tip {
line-height: 1;
padding: 4px 10px;
background: whitesmoke;
color: black;
border-radius: 5px;
border-style: solid;
border-width: 1px;
font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
font-size: 12px;
text-align: left;
}
/* Creates a small triangle extender for the tooltip*/
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: black;
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
</head>
<body onload="PopulateBubbleChart()">
<script src="../D3js/d3.min.js" type="text/javascript"></script>
<script src="../D3js/d3.tip.v0.6.3.js" type="text/javascript"></script>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="../Scripts/jquery-2.0.3.min.js" type="text/javascript"></script>
<script type="text/javascript">
function PopulateBubbleChart() {
var json = { "name": "flare", "children": [{ "name": "US-AL", "children": [{ "name": "AL", "size": 106463, "mcperpatient": 9.11, "displayname": "Alabama" }] }, { "name": "US-AK", "children": [{ "name": "AK", "size": 14693, "mcperpatient": 12.85, "displayname": "Alaska" }] }, { "name": "US-AZ", "children": [{ "name": "AZ", "size": 137362, "mcperpatient": 9.48, "displayname": "Arizona" }] }, { "name": "US-AR", "children": [{ "name": "AR", "size": 85795, "mcperpatient": 10.27, "displayname": "Arkansas" }] }, { "name": "US-CA", "children": [{ "name": "CA", "size": 444432, "mcperpatient": 11.72, "displayname": "California" }] }, { "name": "US-CO", "children": [{ "name": "CO", "size": 90822, "mcperpatient": 9.36, "displayname": "Colorado" }] }, { "name": "US-CT", "children": [{ "name": "CT", "size": 51360, "mcperpatient": 11.1, "displayname": "Connecticut" }] }, { "name": "US-DE", "children": [{ "name": "DE", "size": 14676, "mcperpatient": 10.08, "displayname": "Delaware" }] }, { "name": "US-DC", "children": [{ "name": "DC", "size": 8800, "mcperpatient": 23.2, "displayname": "District of Columbia" }] }, { "name": "US-FL", "children": [{ "name": "FL", "size": 465279, "mcperpatient": 9.21, "displayname": "Florida" }] }, { "name": "US-GA", "children": [{ "name": "GA", "size": 167445, "mcperpatient": 8.4, "displayname": "Georgia" }] }, { "name": "US-HI", "children": [{ "name": "HI", "size": 23824, "mcperpatient": 10.21, "displayname": "Hawaii" }] }, { "name": "US-ID", "children": [{ "name": "ID", "size": 39928, "mcperpatient": 8.33, "displayname": "Idaho" }] }, { "name": "US-IL", "children": [{ "name": "IL", "size": 173998, "mcperpatient": 10.92, "displayname": "Illinois" }] }, { "name": "US-IN", "children": [{ "name": "IN", "size": 122936, "mcperpatient": 9.13, "displayname": "Indiana" }] }, { "name": "US-IA", "children": [{ "name": "IA", "size": 71758, "mcperpatient": 8.09, "displayname": "Iowa" }] }, { "name": "US-KS", "children": [{ "name": "KS", "size": 58097, "mcperpatient": 9.64, "displayname": "Kansas" }] }, { "name": "US-KY", "children": [{ "name": "KY", "size": 101096, "mcperpatient": 9.28, "displayname": "Kentucky" }] }, { "name": "US-LA", "children": [{ "name": "LA", "size": 76489, "mcperpatient": 9.56, "displayname": "Louisiana" }] }, { "name": "US-ME", "children": [{ "name": "ME", "size": 39358, "mcperpatient": 8.52, "displayname": "Maine" }] }, { "name": "US-MD", "children": [{ "name": "MD", "size": 53461, "mcperpatient": 10.43, "displayname": "Maryland" }] }, { "name": "US-MA", "children": [{ "name": "MA", "size": 84345, "mcperpatient": 13.02, "displayname": "Massachusetts" }] }, { "name": "US-MI", "children": [{ "name": "MI", "size": 142558, "mcperpatient": 9.46, "displayname": "Michigan" }] }, { "name": "US-MN", "children": [{ "name": "MN", "size": 108274, "mcperpatient": 9.69, "displayname": "Minnesota" }] }, { "name": "US-MS", "children": [{ "name": "MS", "size": 69676, "mcperpatient": 9.49, "displayname": "Mississippi" }] }, { "name": "US-MO", "children": [{ "name": "MO", "size": 109455, "mcperpatient": 8.59, "displayname": "Missouri" }] }, { "name": "US-MT", "children": [{ "name": "MT", "size": 35189, "mcperpatient": 8.6, "displayname": "Montana" }] }, { "name": "US-NE", "children": [{ "name": "NE", "size": 47275, "mcperpatient": 8.74, "displayname": "Nebraska" }] }, { "name": "US-NV", "children": [{ "name": "NV", "size": 65443, "mcperpatient": 12.04, "displayname": "Nevada" }] }, { "name": "US-NH", "children": [{ "name": "NH", "size": 28604, "mcperpatient": 9.73, "displayname": "New Hampshire" }] }, { "name": "US-NJ", "children": [{ "name": "NJ", "size": 77179, "mcperpatient": 9.71, "displayname": "New Jersey" }] }, { "name": "US-NM", "children": [{ "name": "NM", "size": 48781, "mcperpatient": 10.18, "displayname": "New Mexico" }] }, { "name": "US-NY", "children": [{ "name": "NY", "size": 228820, "mcperpatient": 12.33, "displayname": "New York" }] }, { "name": "US-NC", "children": [{ "name": "NC", "size": 205006, "mcperpatient": 8.73, "displayname": "North Carolina" }] }, { "name": "US-ND", "children": [{ "name": "ND", "size": 18416, "mcperpatient": 8.07, "displayname": "North Dakota" }] }, { "name": "US-OH", "children": [{ "name": "OH", "size": 223944, "mcperpatient": 9.88, "displayname": "Ohio" }] }, { "name": "US-OK", "children": [{ "name": "OK", "size": 90731, "mcperpatient": 8.22, "displayname": "Oklahoma" }] }, { "name": "US-OR", "children": [{ "name": "OR", "size": 96190, "mcperpatient": 9.97, "displayname": "Oregon" }] }, { "name": "US-PA", "children": [{ "name": "PA", "size": 232054, "mcperpatient": 9.07, "displayname": "Pennsylvania" }] }, { "name": "US-RI", "children": [{ "name": "RI", "size": 20132, "mcperpatient": 10.76, "displayname": "Rhode Island" }] }, { "name": "US-SC", "children": [{ "name": "SC", "size": 123070, "mcperpatient": 8.13, "displayname": "South Carolina" }] }, { "name": "US-SD", "children": [{ "name": "SD", "size": 29744, "mcperpatient": 10.32, "displayname": "South Dakota" }] }, { "name": "US-TN", "children": [{ "name": "TN", "size": 135220, "mcperpatient": 9.79, "displayname": "Tennessee" }] }, { "name": "US-TX", "children": [{ "name": "TX", "size": 434233, "mcperpatient": 9.18, "displayname": "Texas" }] }, { "name": "US-UT", "children": [{ "name": "UT", "size": 34062, "mcperpatient": 11.19, "displayname": "Utah" }] }, { "name": "US-VT", "children": [{ "name": "VT", "size": 14925, "mcperpatient": 8.51, "displayname": "Vermont" }] }, { "name": "US-VA", "children": [{ "name": "VA", "size": 87478, "mcperpatient": 9.06, "displayname": "Virginia" }] }, { "name": "US-WA", "children": [{ "name": "WA", "size": 118461, "mcperpatient": 9.17, "displayname": "Washington" }] }, { "name": "US-WV", "children": [{ "name": "WV", "size": 58733, "mcperpatient": 11.12, "displayname": "West Virginia" }] }, { "name": "US-WI", "children": [{ "name": "WI", "size": 117000, "mcperpatient": 10.14, "displayname": "Wisconsin" }] }, { "name": "US-WY", "children": [{ "name": "WY", "size": 18583, "mcperpatient": 10.14, "displayname": "Wyoming" }] }], "minvalue": 8.07, "maxvalue": 23.2, "statecounty": "State" }
$('#mapdiv3').empty();
var color = ["#4F9A85", '#79A163', '#F0C26A', '#C26B50']
try {
var r = 325,
format = d3.format(",d"),
colorScale = d3.scale.quantize()
.domain([json.minvalue, json.maxvalue])
.range(color);
var bubble = d3.layout.pack()
.sort(null)
.size([r, r])
.padding(1);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return json.statecounty + ": <strong>" + d.dispname + "</strong> <br/> Unique Patients**: <strong>" + format(d.value) + "</strong> <br/> Med per Patient: <strong>$" + d.sc + "</strong> <br/>";
})
var vis = d3.select("#mapdiv3").append("svg")
.attr("width", r)
.attr("height", r)
.attr("class", "bubble");
vis.call(tip);
var node = vis.selectAll("g.node")
.data(bubble.nodes(classes(json))
.filter(function (d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
//node.append("title")
// .text(function (d) // { return d.className + ": " + format(d.value); });
// { return "Name: <strong>" + d.className + "</strong> <br/> Unique Patients: <strong>" + format(d.value) + "</strong> <br/> Medical Care per Patient: <strong>" + d.sc + "</strong> <br/>"; });
node.append("circle")
.attr("r", function (d) { return d.r; })
.style("fill", function (d) { return colorScale(d.sc); });
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function (d) { return d.className.substring(0, d.r / 3) });
// Returns a flattened hierarchy containing all leaf nodes under the root.
function classes(root) {
var classes = [];
function recurse(name, node) {
if (node.children) node.children.forEach(function (child) { recurse(node.name, child); });
else {
classes.push({ packageName: name, className: node.name, value: node.size, sc: node.mcperpatient, dispname: node.displayname });
}
}
recurse(null, root);
return { children: classes };
}
}
catch (err) {
alert( err.message);
}
}
</script>
<form id="form1" runat="server">
<div id="mapdiv3" style="height: 300px; width=400px; border: none; text-align: center"></div>
</form>
</body>
</html>
Put the scripts in the HTML head also..
You have the classes function nested in the PopulateBubbleChart function, you likely want to put that on the outside of that function. You then have a similar issue with recurse function. You also do not want to name your function the same name as your array.
You had several issues: here is a jsfiddle you can use to re-piece your code together again: http://jsfiddle.net/ouzo4rje/1/
HTML
<head runat="server">
<title></title>
<script src="../D3js/d3.min.js" type="text/javascript"></script>
<script src="../D3js/d3.tip.v0.6.3.js" type="text/javascript"></script>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="../Scripts/jquery-2.0.3.min.js" type="text/javascript"></script>
</head>
<body onload="PopulateBubbleChart()">
<form id="form1" runat="server">
<div id="mapdiv3" style="height: 300px; width: 400px; border: none; text-align: center;"></div>
</form>
</body>
CSS
.d3-tip {
line-height: 1;
padding: 4px 10px;
background: whitesmoke;
color: black;
border-radius: 5px;
border-style: solid;
border-width: 1px;
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 12px;
text-align: left;
}
/* Creates a small triangle extender for the tooltip*/
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: black;
content:"\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
JS
function PopulateBubbleChart() {
var json = {
"name": "flare",
"children": [{
"name": "US-AL",
"children": [{
"name": "AL",
"size": 106463,
"mcperpatient": 9.11,
"displayname": "Alabama"
}]
}, {
"name": "US-AK",
"children": [{
"name": "AK",
"size": 14693,
"mcperpatient": 12.85,
"displayname": "Alaska"
}]
}, {
"name": "US-AZ",
"children": [{
"name": "AZ",
"size": 137362,
"mcperpatient": 9.48,
"displayname": "Arizona"
}]
}, {
"name": "US-AR",
"children": [{
"name": "AR",
"size": 85795,
"mcperpatient": 10.27,
"displayname": "Arkansas"
}]
}, {
"name": "US-CA",
"children": [{
"name": "CA",
"size": 444432,
"mcperpatient": 11.72,
"displayname": "California"
}]
}, {
"name": "US-CO",
"children": [{
"name": "CO",
"size": 90822,
"mcperpatient": 9.36,
"displayname": "Colorado"
}]
}, {
"name": "US-CT",
"children": [{
"name": "CT",
"size": 51360,
"mcperpatient": 11.1,
"displayname": "Connecticut"
}]
}, {
"name": "US-DE",
"children": [{
"name": "DE",
"size": 14676,
"mcperpatient": 10.08,
"displayname": "Delaware"
}]
}, {
"name": "US-DC",
"children": [{
"name": "DC",
"size": 8800,
"mcperpatient": 23.2,
"displayname": "District of Columbia"
}]
}, {
"name": "US-FL",
"children": [{
"name": "FL",
"size": 465279,
"mcperpatient": 9.21,
"displayname": "Florida"
}]
}, {
"name": "US-GA",
"children": [{
"name": "GA",
"size": 167445,
"mcperpatient": 8.4,
"displayname": "Georgia"
}]
}, {
"name": "US-HI",
"children": [{
"name": "HI",
"size": 23824,
"mcperpatient": 10.21,
"displayname": "Hawaii"
}]
}, {
"name": "US-ID",
"children": [{
"name": "ID",
"size": 39928,
"mcperpatient": 8.33,
"displayname": "Idaho"
}]
}, {
"name": "US-IL",
"children": [{
"name": "IL",
"size": 173998,
"mcperpatient": 10.92,
"displayname": "Illinois"
}]
}, {
"name": "US-IN",
"children": [{
"name": "IN",
"size": 122936,
"mcperpatient": 9.13,
"displayname": "Indiana"
}]
}, {
"name": "US-IA",
"children": [{
"name": "IA",
"size": 71758,
"mcperpatient": 8.09,
"displayname": "Iowa"
}]
}, {
"name": "US-KS",
"children": [{
"name": "KS",
"size": 58097,
"mcperpatient": 9.64,
"displayname": "Kansas"
}]
}, {
"name": "US-KY",
"children": [{
"name": "KY",
"size": 101096,
"mcperpatient": 9.28,
"displayname": "Kentucky"
}]
}, {
"name": "US-LA",
"children": [{
"name": "LA",
"size": 76489,
"mcperpatient": 9.56,
"displayname": "Louisiana"
}]
}, {
"name": "US-ME",
"children": [{
"name": "ME",
"size": 39358,
"mcperpatient": 8.52,
"displayname": "Maine"
}]
}, {
"name": "US-MD",
"children": [{
"name": "MD",
"size": 53461,
"mcperpatient": 10.43,
"displayname": "Maryland"
}]
}, {
"name": "US-MA",
"children": [{
"name": "MA",
"size": 84345,
"mcperpatient": 13.02,
"displayname": "Massachusetts"
}]
}, {
"name": "US-MI",
"children": [{
"name": "MI",
"size": 142558,
"mcperpatient": 9.46,
"displayname": "Michigan"
}]
}, {
"name": "US-MN",
"children": [{
"name": "MN",
"size": 108274,
"mcperpatient": 9.69,
"displayname": "Minnesota"
}]
}, {
"name": "US-MS",
"children": [{
"name": "MS",
"size": 69676,
"mcperpatient": 9.49,
"displayname": "Mississippi"
}]
}, {
"name": "US-MO",
"children": [{
"name": "MO",
"size": 109455,
"mcperpatient": 8.59,
"displayname": "Missouri"
}]
}, {
"name": "US-MT",
"children": [{
"name": "MT",
"size": 35189,
"mcperpatient": 8.6,
"displayname": "Montana"
}]
}, {
"name": "US-NE",
"children": [{
"name": "NE",
"size": 47275,
"mcperpatient": 8.74,
"displayname": "Nebraska"
}]
}, {
"name": "US-NV",
"children": [{
"name": "NV",
"size": 65443,
"mcperpatient": 12.04,
"displayname": "Nevada"
}]
}, {
"name": "US-NH",
"children": [{
"name": "NH",
"size": 28604,
"mcperpatient": 9.73,
"displayname": "New Hampshire"
}]
}, {
"name": "US-NJ",
"children": [{
"name": "NJ",
"size": 77179,
"mcperpatient": 9.71,
"displayname": "New Jersey"
}]
}, {
"name": "US-NM",
"children": [{
"name": "NM",
"size": 48781,
"mcperpatient": 10.18,
"displayname": "New Mexico"
}]
}, {
"name": "US-NY",
"children": [{
"name": "NY",
"size": 228820,
"mcperpatient": 12.33,
"displayname": "New York"
}]
}, {
"name": "US-NC",
"children": [{
"name": "NC",
"size": 205006,
"mcperpatient": 8.73,
"displayname": "North Carolina"
}]
}, {
"name": "US-ND",
"children": [{
"name": "ND",
"size": 18416,
"mcperpatient": 8.07,
"displayname": "North Dakota"
}]
}, {
"name": "US-OH",
"children": [{
"name": "OH",
"size": 223944,
"mcperpatient": 9.88,
"displayname": "Ohio"
}]
}, {
"name": "US-OK",
"children": [{
"name": "OK",
"size": 90731,
"mcperpatient": 8.22,
"displayname": "Oklahoma"
}]
}, {
"name": "US-OR",
"children": [{
"name": "OR",
"size": 96190,
"mcperpatient": 9.97,
"displayname": "Oregon"
}]
}, {
"name": "US-PA",
"children": [{
"name": "PA",
"size": 232054,
"mcperpatient": 9.07,
"displayname": "Pennsylvania"
}]
}, {
"name": "US-RI",
"children": [{
"name": "RI",
"size": 20132,
"mcperpatient": 10.76,
"displayname": "Rhode Island"
}]
}, {
"name": "US-SC",
"children": [{
"name": "SC",
"size": 123070,
"mcperpatient": 8.13,
"displayname": "South Carolina"
}]
}, {
"name": "US-SD",
"children": [{
"name": "SD",
"size": 29744,
"mcperpatient": 10.32,
"displayname": "South Dakota"
}]
}, {
"name": "US-TN",
"children": [{
"name": "TN",
"size": 135220,
"mcperpatient": 9.79,
"displayname": "Tennessee"
}]
}, {
"name": "US-TX",
"children": [{
"name": "TX",
"size": 434233,
"mcperpatient": 9.18,
"displayname": "Texas"
}]
}, {
"name": "US-UT",
"children": [{
"name": "UT",
"size": 34062,
"mcperpatient": 11.19,
"displayname": "Utah"
}]
}, {
"name": "US-VT",
"children": [{
"name": "VT",
"size": 14925,
"mcperpatient": 8.51,
"displayname": "Vermont"
}]
}, {
"name": "US-VA",
"children": [{
"name": "VA",
"size": 87478,
"mcperpatient": 9.06,
"displayname": "Virginia"
}]
}, {
"name": "US-WA",
"children": [{
"name": "WA",
"size": 118461,
"mcperpatient": 9.17,
"displayname": "Washington"
}]
}, {
"name": "US-WV",
"children": [{
"name": "WV",
"size": 58733,
"mcperpatient": 11.12,
"displayname": "West Virginia"
}]
}, {
"name": "US-WI",
"children": [{
"name": "WI",
"size": 117000,
"mcperpatient": 10.14,
"displayname": "Wisconsin"
}]
}, {
"name": "US-WY",
"children": [{
"name": "WY",
"size": 18583,
"mcperpatient": 10.14,
"displayname": "Wyoming"
}]
}],
"minvalue": 8.07,
"maxvalue": 23.2,
"statecounty": "State"
}
$('#mapdiv3').empty();
var color = ["#4F9A85", '#79A163', '#F0C26A', '#C26B50']
try {
var r = 325,
format = d3.format(",d"),
colorScale = d3.scale.quantize()
.domain([json.minvalue, json.maxvalue])
.range(color);
var bubble = d3.layout.pack()
.sort(null)
.size([r, r])
.padding(1);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return json.statecounty + ": <strong>" + d.dispname + "</strong> <br/> Unique Patients**: <strong>" + format(d.value) + "</strong> <br/> Med per Patient: <strong>$" + d.sc + "</strong> <br/>";
});
var vis = d3.select("#mapdiv3").append("svg")
.attr("width", r)
.attr("height", r)
.attr("class", "bubble");
vis.call(tip);
var node = vis.selectAll("g.node")
.data(bubble.nodes(classes(json))
.filter(function (d) {
return !d.children;
}))
.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
//node.append("title")
// .text(function (d) // { return d.className + ": " + format(d.value); });
// { return "Name: <strong>" + d.className + "</strong> <br/> Unique Patients: <strong>" + format(d.value) + "</strong> <br/> Medical Care per Patient: <strong>" + d.sc + "</strong> <br/>"; });
node.append("circle")
.attr("r", function (d) {
return d.r;
})
.style("fill", function (d) {
return colorScale(d.sc);
});
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function (d) {
return d.className.substring(0, d.r / 3)
});
} catch (err) {
alert(err.message);
}
}
// Returns a flattened hierarchy containing all leaf nodes under the root.
var arrClasses = [];
function classes(root) {
recurse(null, root);
return {
children: arrClasses
};
}
function recurse(name, node) {
if (node.children) {
node.children.forEach(function (child) {
recurse(node.name, child);
});
} else {
arrClasses.push({
packageName: name,
className: node.name,
value: node.size,
sc: node.mcperpatient,
dispname: node.displayname
});
}
}