Create dynamic Word Cloud using d3.js - json

I am using the following example as base and want to make it dynamic word cloud
https://github.com/jasondavies/d3-cloud
The data is added to the array but my word-cloud is not reflecting the newly added word(s):
<script>
var fill = d3.scale.category20();
var data = [{word:"Hello",weight:20},{word:"World",weight:10},{word:"Normally",weight:25},{word:"You",weight:15},{word:"Want",weight:30},{word:"More",weight:12},{word:"Words",weight:8},{word:"But",weight:18},{word:"Who",weight:22},{word:"Cares",weight:27}];
d3.layout.cloud().size([500, 500])
.words(data.map(function(d) {
return {text: d.word, size: d.weight};
}))
.padding(5)
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
function draw(words) {
d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(150,150)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
function drawUpdate(words){
//alert(JSON.stringify(words)); //shows me the added data
d3.select("body").selectAll("text")
.data(words.map(function(d) {
return {text: d.word, size: d.weight};
}))
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.text(function(d) { return d.text; });
}
setInterval(function () {
var d_new = data;
d_new.push({word: "Mappy",weight:35});
drawUpdate(d_new);
}, 1500);
</script>
Also, it refreshed the first time, but without the new word added. Could someone please rectify or point out what am I doing wrong in this.
Thanks

Thanks to Larks I was able to get it done. Here I am sharing the code if anyone else faces a similar issue, I hope it can help
<script>
var fill = d3.scale.category20();
var data = [{word:"Hello",weight:20},{word:"World",weight:10},{word:"Normally",weight:25},{word:"You",weight:15},{word:"Want",weight:30},{word:"More",weight:12},{word:"Words",weight:8},{word:"But",weight:18},{word:"Who",weight:22},{word:"Cares",weight:27}];
d3.layout.cloud().size([500, 500])
.words(data.map(function(d) {
return {text: d.word, size: d.weight};
}))
.padding(5)
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
function draw(words) {
d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(150,150)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
function drawUpdate(words){
d3.layout.cloud().size([500, 500])
.words(words)
.padding(5)
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; })
.start();
d3.select("svg")
.selectAll("g")
.attr("transform", "translate(150,150)")
.selectAll("text")
.data(words).enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
setInterval(function () {
var d_new = data;
d_new.push({word:randomWord(),weight:randomWeight()});
drawUpdate(d_new.map(function(d) {
return {text: d.word, size: d.weight};
}));
}, 1500);
function randomWord() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
function randomWeight(){
var r = Math.round(Math.random() * 100);
return r;
}
</script>

Related

D3 Multi Series Line Chart

I am trying to create a D3 line chart. I have copied the code from the block builder and replaced with my data. Although the code is working but its not showing the labels when i hover the line.
I want to basically get the label details when I hover over the line.
Original Block https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91
Regards,
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px Helvetica;
}
.axis line {
fill: red;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 3px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 50, right: 50, bottom: 30, left: 80},
width = 630 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.Year,
temperature: +d[name]
};
})
};
});
var xAxis = d3.svg.axis()
.scale(x)
.ticks(10)
.innerTickSize(2)
.outerTickSize(0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat(function(d) { return d ;})
.ticks(10)
.innerTickSize(2.5)
.outerTickSize(0)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("https://gist.githubusercontent.com/vaibhavjaitly/f1339c2bc02857afdf65b8d572dc31e5/raw/72ad1af2eacc86575649ae015b433aacb37f3854/US.and.SF.Crimerate.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Year"; }));
data.forEach(function(d) {
d.date = parseDate(d.Year);
});
var companies = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, price: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(companies, function(c) { return d3.min(c.values, function(v) { return v.price; }); }),
d3.max(companies, function(c) { return d3.max(c.values, function(v) { return v.price; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Crime Rate per 10,000");
svg.append("line")
.attr(
{
"class":"horizontalGrid",
"x1" : 0,
"x2" : width,
"y1" : y(0),
"y2" : y(0),
"fill" : "none",
"shape-rendering" : "crispEdges",
"stroke" : "black",
"stroke-width" : "1px",
"stroke-dasharray": ("3, 3")
});
var company = svg.selectAll(".company")
.data(companies)
.enter().append("g")
.attr("class", "company");
var path = svg.selectAll(".company").append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name)
});
var totalLength = [path[0][0].getTotalLength(), path[0][1].getTotalLength()];
console.log(totalLength);
d3.select(path[0][0])
.attr("stroke-dasharray", totalLength[0] + " " + totalLength[0] )
.attr("stroke-dashoffset", totalLength[0])
.transition()
.duration(15000)
.ease("linear")
.attr("stroke-dashoffset", 0);
d3.select(path[0][1])
.attr("stroke-dasharray", totalLength[1] + " " + totalLength[1] )
.attr("stroke-dashoffset", totalLength[1])
.transition()
.duration(15000)
.ease("linear")
.attr("stroke-dashoffset", 0);
});
var mouseG = svg.append("g")
.attr("class", "mouse-over-effects");
mouseG.append("path") // this is the black vertical line to follow mouse
.attr("class", "mouse-line")
.style("stroke", "black")
.style("stroke-width", "1px")
.style("opacity", "0");
var lines = document.getElementsByClassName('line');
var mousePerLine = mouseG.selectAll('.mouse-per-line')
.data(cities)
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.append("circle")
.attr("r", 7)
.style("stroke", function(d) {
return color(d.Year);
})
.style("fill", "none")
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.append("text")
.attr("transform", "translate(10,3)");
mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
.attr('width', width) // can't catch mouse events on a g element
.attr('height', height)
.attr('fill', 'none')
.attr('pointer-events', 'all')
.on('mouseout', function() { // on mouse out hide line, circles and text
d3.select(".mouse-line")
.style("opacity", "0");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "0");
d3.selectAll(".mouse-per-line text")
.style("opacity", "0");
})
.on('mouseover', function() { // on mouse in show line, circles and text
d3.select(".mouse-line")
.style("opacity", "1");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "1");
d3.selectAll(".mouse-per-line text")
.style("opacity", "1");
})
.on('mousemove', function() { // mouse moving over canvas
var mouse = d3.mouse(this);
d3.select(".mouse-line")
.attr("d", function() {
var d = "M" + mouse[0] + "," + height;
d += " " + mouse[0] + "," + 0;
return d;
});
d3.selectAll(".mouse-per-line")
.attr("transform", function(d, i) {
console.log(width/mouse[0])
var xDate = x.invert(mouse[0]),
bisect = d3.bisector(function(d) { return d.Year; }).right;
idx = bisect(d.values, xYear);
var beginning = 0,
end = lines[i].getTotalLength(),
target = null;
while (true){
target = Math.floor((beginning + end) / 2);
pos = lines[i].getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== mouse[0]) {
break;
}
if (pos.x > mouse[0]) end = target;
else if (pos.x < mouse[0]) beginning = target;
else break; //position found
}
d3.select(this).select('text')
.text(y.invert(pos.y).toFixed(2));
return "translate(" + mouse[0] + "," + pos.y +")";
});
});
</script>
Minor change:
The "date" column being used in the code is based on the reference data. In your case, it should be changed to "Year".
Changing:
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
to
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Year"; }));
and
d.date = parseDate(d.date);
to
d.date = parseDate(d.Year);
Here's a new block:
https://bl.ocks.org/shashank2104/8d4aa05b7cf14d15099e0a0c47476f0e/d0c76a98426d7524b97f5c815b05c3d91d5b6dd0
Hope this helps.

Legend text background change on mouse-hover over d3 doughnut chart

I have one doughnut chart whose values display on mouse-hover. But, I want to change the legend text background while hovering over the respective doughnut chart area.
return {
restrict: 'E',
scope: {
values: '='
},
link: function (scope, element, attrs) {
scope.$watch('values', function(values) {
var data = [];
if(values) {
console.log('values from directive: ', values);
var w = 700,
h = 700,
r = 290,
inner = 190,
color = d3.scale.category20();
data=values;
var total = d3.sum(data, function(d) {
return d3.sum(d3.values(d));
});
var vis = d3.select("#pieChartsD3")
.append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" +320+ "," +320+ ")")
var textTop = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textTop")
.text( "TOTAL" )
.attr("y", -10),
textBottom = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textBottom")
.text(total.toFixed(0) )
.attr("y", 10);
var arc = d3.svg.arc()
.innerRadius(inner)
.outerRadius(r);
var arcOver = d3.svg.arc()
.innerRadius(inner + 20)
.outerRadius(r + 20);
var pie = d3.layout.pie()
.value(function(d) { return d.val; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice")
.style('word-wrap', 'break-word')
.on("mouseover", function(d) {
d3.select(this).select("path").transition()
.duration(200)
.attr("d", arcOver)
textTop.text(d3.select(this).datum().data.name)
.style('fill', 'red')
.attr("y", -10);
textBottom.text(d3.select(this).datum().data.val.toFixed(0))
.style('fill', 'blue')
.attr("y", 10);
})
.on("mouseout", function(d) {
d3.select(this).select("path").transition()
.duration(100)
.attr("d", arc);
textTop.text( "TOTAL" )
.attr("y", -10);
textBottom.text(total.toFixed(0));
});
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc);
console.log("datas length: "+data.length)
var legend = d3.select("#legend").append("svg")
.attr("class", "legend")
.attr("width", 400)
.attr("height", 20*data.length)
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) { return color(i); });
legend.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
}
})
}
}
(BTW I'm inferring about your request because you haven't explicitly stated a question. With that said...)
Inside the .on("mouseover", function(d) { block, add another section:
legend.filter(function(l){
l === d; // remember d is the value bound to the donut segment
})
.attr("fill","yellow")
And be sure to write the logic to undo it, by setting fill back to grey or none, in .on("mouseout".

How increase height dynamically by fixing width of the rect box in d3 js

I'm using d3 js for collapsing tree.
I want to fix the width of the rectangle.
If text size in rectangle box is more than the fixed width of rect box how to increase height of rect box dynamically?
Like below image I want the output.
Here is the code what I'm using
.node {
cursor: pointer;
border-style: solid;
border-width: 2px 10px 4px 20px;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node rect {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var treeData = [
{
"name": "Top Level",
"parent": "null",
"children": [
{
"name": "Level 2: A. Some text here Some text here Some text here",
"parent": "Top Level",
"children": [
{
"name": "Son of A",
"parent": "Level 2: A"
},
{
"name": "Daughter of A",
"parent": "Level 2: A"
}
]
},
{
"name": "Level 2: B",
"parent": "Top Level"
}
]
}
];
// ************** Generate the tree diagram *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.source(function (d) {
return {
"x": d.source.x,
"y": d.source.y + 150
};
})
.projection(function (d) { return [d.y + 0, d.x + 0];
});
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 + ")");
root = treeData[0];
root.x0 = height / 2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "500px");
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 * 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's 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("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? 15 : 15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", 60)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? -15 : -15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 150)
.attr("height", 30)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1)
.attr("text-anchor", "middle");
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? 15 : 15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 10)
.attr("height", 10);
nodeExit.select("text")
.style("fill-opacity", 1e-6)
.attr("text-anchor", "middle");
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("fill", "none")
.attr("stroke", "black")
.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'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;
});
}
// 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>
Just a superficial attempt.
First add all the text elements
Wrap the text element within certain width using tspans
Get the height of the text element and store as an attribute it in the data itself
Use the stored attribute for setting the height of the rectangle
Reference for wrapping text here. You can always write custom wrapping function.
Hope this helps
var treeData = [
{
"name": "Top Level",
"parent": "null",
"children": [
{
"name": "Level 2: A. Some text here Some text here Some text here Some text here",
"parent": "Top Level",
"children": [
{
"name": "Son of A Some text here Some text here",
"parent": "Level 2: A"
},
{
"name": "Daughter of A Some text here Some text here Some text here Some text here Some text here",
"parent": "Level 2: A"
}
]
},
{
"name": "Level 2: B Some text here Some text here Some text here",
"parent": "Top Level"
}
]
}
];
// ************** Generate the tree diagram *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.source(function (d) {
return {
"x": d.source.x,
"y": d.source.y + 150
};
})
.projection(function (d) { return [d.y + 0, d.x + 0];
});
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 + ")");
root = treeData[0];
root.x0 = height / 2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "500px");
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 * 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's 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("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? 15 : 15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", 60)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6)
.each(function(d) {
calculateTextWrap(this,d);
});
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? -15 : -15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 150)
.attr("height", function(d) { return d.rectHeight})
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1)
.attr("text-anchor", "middle");
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("rect")
.attr("x", function(d) { return d.children || d._children ? 0 : 0; })
.attr("y", function(d) { return d.children || d._children ? 15 : 15; })
.attr("rx", 10)
.attr("ry", 10)
.attr("width", 10)
.attr("height", 10);
nodeExit.select("text")
.style("fill-opacity", 1e-6)
.attr("text-anchor", "middle");
function calculateTextWrap(element, data) {
var text = d3.select(element);
if (text.node().getComputedTextLength() < 150) {
//console.log("No need to wrap");
} else {
var words = text.text().split("").reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(0.35),
tspan = text.text(null).append("tspan").attr("text-anchor", "start").attr("x", 5).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(""));
if (tspan.node().getComputedTextLength() > 150) {
lineNumber++;
line.pop();
tspan.text(line.join(""));
line = [word];
tspan = text.append("tspan").attr("text-anchor", "start").attr("x", 5).attr("y", y).attr("dy", lineHeight + dy + "em").text(word);
}
}
}
var rectHeight = text.node().getBBox().height;
if(rectHeight < 30) rectHeight = 30;
data.rectHeight = rectHeight + 10 ;
}
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("fill", "none")
.attr("stroke", "black")
.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'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;
});
}
// 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);
}
.node {
cursor: pointer;
border-style: solid;
border-width: 2px 10px 4px 20px;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node rect {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>
try to add this to your styling :
.node {
height: fit-content;
width: fit-content;
padding: .5rem;
}
It fits the height and size of the node class to the content (text) of the element. It should do the trick.

building d3 force directed graph using dynamic json data

my current D3 with static json looks like
var graph = {
"nodes":[
{"name":"User Login","group":1},
{"name":"Appointments","group":1},
{"name":"Store Visit","group":1},
{"name":"Visit History","group":1},
{"name":"Resume Store Visit","group":1}
],
"links":[
{"source":1,"target":0,"value":1},
{"source":2,"target":0,"value":8},
{"source":3,"target":0,"value":10},
{"source":3,"target":2,"value":6},
{"source":4,"target":0,"value":1}
]
};
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(300)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
force
.nodes(graph.nodes)
.links(graph.links)
.start();
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.attr("marker-end", "url(#end)")
.style("stroke-width", function(d) {
return Math.sqrt(d.value);
});
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.call(force.drag);
node.append("rect")
.attr("class", "node")
.attr("width", 100)
.attr("height", 35)
.style("fill", function(d) {
return color(d.group);
})
.style("stroke", "black")
.style("stroke-width", "1px");
node.append("text")
.text(function(d) {
return d.name + '(' + d.group + ')';
})
.style("font-size", "12px")
.attr("dy", "1em");
node.append("title")
.text(function(d) {
return d.name;
});
force.on("tick", function() {
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 + ")";
});
});
</script>
I want to move the static data to move to a js file and fetch it using my rest service like i am doing for other morris charts where the script looks like
$.ajax({ url: 'http://127.0.0.1:7101/MUDRESTService/rest/v1/meventsbydaybar?onlyData=true&limit=99',
type: 'get',
dataType: 'json',
success: function(output) {
var ddata = JSON.stringify(output.items);
var arr = JSON.parse(ddata);
bar.setData(arr);
}
});
Please advise how to use my above rest service as a source for the d3 graph
using
var data; // a global
d3.json("http://127.0.0.1:7101/MUDRESTService/rest/v1/mudstats?onlyData=true", function(error, json) {
data = json;
});
worked for me

Unable to create bar chart from d3 using URL

I am trying to create bar chart from json file which is a URL but i am unable to do so please help me, as i am new to d3. The code is here please tell me where i am making mistake.
var width = 960,
height = 500;
var y = d3.scale.linear().range([height, 0]);
var chart = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
generateChart();
function generateChart() {
d3.json('http://dataserver.org:8009/topic/domain/cancer',
function(error, data) {
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};
It is not a problem of cross domain as I checked your API. Assuming that you are fetching d3.js from CDN, I am suggesting a change. Your chart will depend on "institute" as it is containing all the required values for chart. So I changed it as per structure your API's response.
**in some case data was coming as "undefined" so I am fetching d3.js from CDN
Here is whole modified file:-
function generateChart() {
d3.json('http://srvgal78.deri.ie:8009/topic/domain/cancer',
function(error, data) {
data = data.institute;
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};