D3 Sankey diagram links do not cover the entire node height - javascript

I am using D3.js to produce Sankey diagrams, and I'm not satisfied with the resulting connection between nodes, particularly when the total input of a node is different from its total output.
As an example:
// set the dimensions and margins of the data
var margin = { top: 10, right: 10, bottom: 10, left: 10 },
width = 300 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#graph").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 + ")");
// Set the sankey diagram properties
var sankey = d3.sankey()
.nodeWidth(10)
.nodePadding(10)
.size([width, height]);
data = {
"nodes": [
{ "node": 0, "name": "A" },
{ "node": 1, "name": "B" },
{ "node": 2, "name": "C" }
],
"links": [
{ "source": 0, "target": 1, "value": 2 },
{ "source": 1, "target": 2, "value": 1 }
]
}
// Constructs a new Sankey generator with the default settings.
sankey
.nodes(data.nodes)
.links(data.links)
.layout(1);
// add in the links
svg.append("g")
.selectAll(".link")
.data(data.links)
.enter()
.append("path")
.attr("class", "link")
.attr("d", sankey.link())
.style("stroke-width", function (d) { return Math.max(1, d.dy); })
// add in the nodes
var node = svg.append("g")
.selectAll(".node")
.data(data.nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
// add the rectangles for the nodes
node.append("rect")
.attr("height", function (d) { return d.dy; })
.attr("width", sankey.nodeWidth())
// add in the title for the nodes
node.append("text")
.attr("x", -6)
.attr("y", function (d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function (d) { return d.name; })
.filter(function (d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start")
<body>
<style>
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
</style>
<div id="graph"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery#master/LIB/sankey.js"></script>
<script src="test.js"></script>
</body>
This produces:
But without chaning the input data I would like:
Meaning the node size is determined by the link value, but the link size matches both the input and the output nodes.

Related

D3.js Adding legend to the Responsive bar chart

I have found a simple responsive bar chart from this Link. So, I have done some little modification into this and also added legends into bar chart. Chart is responsive but not the legends. I have been working on this since days. I have tried appending legends into x-axis that doesn't work also.
<!doctype html>
<html lang="en">
<head>
<title>Bootstrap Case</title>
<meta charset="utf-8">
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<style>
.axis path,
.axis line {
fill: none;
stroke: #bdbdbd;
}
.axis text {
font-family: 'Open Sans regular', 'Open Sans';
font-size: 13px;
}
.bar {
fill: #8bc34a;
}
.bar:hover {
fill: #039be4;
}
</style>
<div id ="chartID"></div>
<script>
var data = [{
"letter": "a",
"frequency": "4.84914547592537",
"Color": "#D3D3D3"
},
{
"letter": "b",
"frequency": "4.86872684269123",
"Color": "#D3D3D3"
},
{
"letter": "c",
"frequency": "6.63842861065779",
"Color": "#000000"
},
{
"letter": "d",
"frequency": "6.53280838923937",
"Color": "#000000"
}
]
var data2 = [];
for (var i = 0; i < 2; i++) {
data2.push(data[i]);
}
var color_hash = {
0: ["Control", "#D3D3D3"],
1: ["Case", "#000000"]
}
var margin = {
top: 30,
right: 100,
bottom: 20,
left: 80
};
var width = 960 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var xScale = d3.scale.ordinal().rangeRoundBands([0, width], .1)
var yScale = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var svgContainer = d3.select("#chartID").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 + ")");
xScale.domain(data.map(function (d) {
return d.letter;
}));
yScale.domain([0, d3.max(data, function (d) {
return d.frequency;
})]);
var xAxis_g = svgContainer.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
var yAxis_g = svgContainer.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("dx", "-10em")
.attr("transform", "rotate(-90)")
.attr("y", 6).attr("dy", "-4.0em")
.style("text-anchor", "end").text("Expression values");
svgContainer.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) {
return xScale(d.letter);
})
.attr("width", xScale.rangeBand())
.attr("y", function (d) {
return yScale(d.frequency);
})
.attr("height", function (d) {
return height - yScale(d.frequency);
})
.style("fill", function (d) {
return d.Color;
});
// Add Legends
var legend = svgContainer.append("g")
// .attr("transform", "translate(0," + (10) + ")")
// .attr("x", width - 100)
// .attr("y", 250)
// .attr("height", 100)
// .attr("width", 100);
legend.selectAll('g').data(data2)
.enter()
.append('g')
.each(function (d, i) {
var g = d3.select(this);
g.append("rect")
// .attr("class", "legend")
.attr("x", width)
.attr("y", i * 25)
.attr("width", 10)
.attr("height", 10)
.style("fill", color_hash[String(i)][1]);
g.append("text")
// .attr("class", "legend")
.attr("x", width - 20 * -1)
.attr("y", i * 25 + 8)
// .attr("height", 30)
// .attr("width", 100)
// .style("text-anchor", "end")
.style("font-size", 16)
.text(color_hash[String(i)][0]);
});
d3.select(window).on('resize', resize);
function resize() {
// console.log('----resize function----');
// update width
width = parseInt(d3.select('#chartID').style('width'), 10);
width = width - margin.left - margin.right;
height = parseInt(d3.select("#chartID").style("height"));
height = height - margin.top - margin.bottom;
// console.log('----resiz width----' + width);
// console.log('----resiz height----' + height);
// resize the chart
if (width < 870) {
//xScale.range([0, width]);
xScale.rangeRoundBands([0, width], .1);
yScale.range([height, 0]);
yAxis.ticks(Math.max(height / 50, 2));
xAxis.ticks(Math.max(width / 50, 2));
d3.select(svgContainer.node().parentNode)
.style('width', (width + margin.left + margin.right) + 'px');
svgContainer.selectAll('.bar')
.attr("x", function (d) {
return xScale(d.letter);
})
.attr("width", xScale.rangeBand());
// svgContainer.selectAll('.legend')
// .attr("x", function (d) {
// return ;
// })
// .attr("width", xScale.rangeBand());
svgContainer.select('.x.axis').call(xAxis.orient('bottom'));
// svgContainer.select('.legend');
}
}
</script>
</html>
Need some help for this.
Thank you.

How do I make these data grouped bars closer together in D3?

I'm trying to fix the margins for grouped bars in my D3.js chart.
Right now, it has ugly gaps like this:
But I need it to look more like this for each group, centered on the x-axis labels (Month and Year):
I think this line of code is the culprit, but I don't know how to modify it:
.attr("x", function(d) { return x1(d.grpName); })
Please see the code snippet below as a full page.
const groupData = [
{ key: "Jan. 2020", values:
[
{grpName:'Team1', grpValue:26},
{grpName:'Team2', grpValue:15},
{grpName:'Team3', grpValue:48}
]
},
{ key: "Feb.2020", values:
[
{grpName:'Team1', grpValue:14},
{grpName:'Team2', grpValue:23},
{grpName:'Team3', grpValue:5}
]
},
{ key: "March 2020", values:
[
{grpName:'Team1', grpValue:32},
{grpName:'Team2', grpValue:9},
{grpName:'Team3', grpValue:25}
]
},
{ key: "April 2020", values:
[
{grpName:'Team1', grpValue:41},
{grpName:'Team2', grpValue:55},
{grpName:'Team3', grpValue:26}
]
}
];
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x0 = d3.scaleBand().rangeRound([0, width], .5);
var x1 = d3.scaleBand();
var y = d3.scaleLinear().rangeRound([height, 0]);
var xAxis = d3.axisBottom().scale(x0)
var yAxis = d3.axisLeft().scale(y);
const color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select('#barChart')
.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 + ")");
var categoriesNames = groupData.map(function(d) { return d.key; });
var rateNames = groupData[0].values.map(function(d) { return d.grpName; });
x0.domain(categoriesNames);
x1.domain(rateNames).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(groupData, function(key) { return d3.max(key.values, function(d) { return d.grpValue; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.style('opacity','0')
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.text("Value");
svg.select('.y').transition().duration(500).delay(1300).style('opacity','1');
var slice = svg.selectAll(".slice")
.data(groupData)
.enter().append("g")
.attr("class", "g")
.attr("transform",function(d) { return "translate(" + x0(d.key) + ",0)"; });
slice.selectAll("rect")
.data(function(d) { return d.values; })
.enter().append("rect")
.attr("width", "35")
.attr("x", function(d) { return x1(d.grpName); })
.style("fill", function(d) { return color(d.grpName) })
.attr("y", function(d) { return y(0); })
.attr("height", function(d) { return height - y(0); })
.on("mouseover", function(d) {
d3.select(this).style("fill", d3.rgb(color(d.grpName)).darker(2));
})
.on("mouseout", function(d) {
d3.select(this).style("fill", color(d.grpName));
});
slice.selectAll("rect")
.transition()
.delay(function (d) {return Math.random()*1000;})
.duration(1000)
.attr("y", function(d) { return y(d.grpValue); })
.attr("height", function(d) { return height - y(d.grpValue); });
//Legend
var legend = svg.selectAll(".legend")
.data(groupData[0].values.map(function(d) { return d.grpName; }).reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d,i) { return "translate(0," + i * 20 + ")"; })
.style("opacity","0");
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d) { return color(d); });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {return d; });
legend.transition().duration(500).delay(function(d,i){ return 1300 + 100 * i; }).style("opacity","1");
.axis path,
.axis line {
fill: none;
stroke: #000;\
shape-rendering: crispEdges;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="barChart"></div>
You have two x scales, x0 and x1, the first placing the groups, the second placing the bars in each group. However, while you use x0.bandwidth() to define the width of each group, you use 35 to define the width of each bar.
If x0.bandwidth() is smaller than, or much greater than, 35 times the number of bars we get some awkward positioning.
Instead, you should use x1.bandwidth() to set the bar width, just as you used x0.bandwidth to set the group width (the range of x1).
If you use x1.bandwidth() to set bar width, you get bars that touch adjacent bars, but now you can use scaleBand.padding() to set margin between group and bar:
x0.padding(0.1); // space the groups: bandwidth 90% of original, now with 10% margin
x1.padding(0.1); // same for spacing the bars
Taken together:
const groupData = [
{ key: "Jan. 2020", values:
[
{grpName:'Team1', grpValue:26},
{grpName:'Team2', grpValue:15},
{grpName:'Team3', grpValue:48}
]
},
{ key: "Feb.2020", values:
[
{grpName:'Team1', grpValue:14},
{grpName:'Team2', grpValue:23},
{grpName:'Team3', grpValue:5}
]
},
{ key: "March 2020", values:
[
{grpName:'Team1', grpValue:32},
{grpName:'Team2', grpValue:9},
{grpName:'Team3', grpValue:25}
]
},
{ key: "April 2020", values:
[
{grpName:'Team1', grpValue:41},
{grpName:'Team2', grpValue:55},
{grpName:'Team3', grpValue:26}
]
}
];
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x0 = d3.scaleBand().rangeRound([0, width], .5).padding(0.1);
var x1 = d3.scaleBand().padding(0.1);
var y = d3.scaleLinear().rangeRound([height, 0]);
var xAxis = d3.axisBottom().scale(x0)
var yAxis = d3.axisLeft().scale(y);
const color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select('#barChart')
.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 + ")");
var categoriesNames = groupData.map(function(d) { return d.key; });
var rateNames = groupData[0].values.map(function(d) { return d.grpName; });
x0.domain(categoriesNames);
x1.domain(rateNames).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(groupData, function(key) { return d3.max(key.values, function(d) { return d.grpValue; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.style('opacity','0')
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.text("Value");
svg.select('.y').transition().duration(500).delay(1300).style('opacity','1');
var slice = svg.selectAll(".slice")
.data(groupData)
.enter().append("g")
.attr("class", "g")
.attr("transform",function(d) { return "translate(" + x0(d.key) + ",0)"; });
slice.selectAll("rect")
.data(function(d) { return d.values; })
.enter().append("rect")
.attr("width", x1.bandwidth())
.attr("x", function(d) { return x1(d.grpName); })
.style("fill", function(d) { return color(d.grpName) })
.attr("y", function(d) { return y(0); })
.attr("height", function(d) { return height - y(0); })
.on("mouseover", function(d) {
d3.select(this).style("fill", d3.rgb(color(d.grpName)).darker(2));
})
.on("mouseout", function(d) {
d3.select(this).style("fill", color(d.grpName));
});
slice.selectAll("rect")
.transition()
.delay(function (d) {return Math.random()*1000;})
.duration(1000)
.attr("y", function(d) { return y(d.grpValue); })
.attr("height", function(d) { return height - y(d.grpValue); });
//Legend
var legend = svg.selectAll(".legend")
.data(groupData[0].values.map(function(d) { return d.grpName; }).reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d,i) { return "translate(0," + i * 20 + ")"; })
.style("opacity","0");
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d) { return color(d); });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {return d; });
legend.transition().duration(500).delay(function(d,i){ return 1300 + 100 * i; }).style("opacity","1");
.axis path,
.axis line {
fill: none;
stroke: #000;\
shape-rendering: crispEdges;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="barChart"></div>

D3 - Getting text on the top of rectangles in Vertical Bar chart

I am making a vertical bar chart with D3 successfully. I further want the value of frequency to lie on the top of each rectangle. I am able to get the complete structure and rectangles. But, I cannot see my values residing on top of the bars. Can someone help out?
SNIPPET:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<svg></svg>
<script>
//module declaration
var app = angular.module('myApp',[]);
//Controller declaration
app.controller('myCtrl',function($scope){
$scope.svgWidth = 800;//svg Width
$scope.svgHeight = 500;//svg Height
//Data in proper format
var data = [
{"letter": "A","frequency": "5.01"},
{"letter": "B","frequency": "7.80"},
{"letter": "C","frequency": "15.35"},
{"letter": "D","frequency": "22.70"},
{"letter": "E","frequency": "34.25"},
{"letter": "F","frequency": "10.21"},
{"letter": "G","frequency": "7.68"},
];
//removing prior svg elements ie clean up svg
d3.select('svg').selectAll("*").remove();
//resetting svg height and width in current svg
d3.select("svg").attr("width", $scope.svgWidth).attr("height", $scope.svgHeight);
//Setting up of our svg with proper calculations
var svg = d3.select("svg");
var margin = {top: 20, right: 20, bottom: 30, left: 40};
var width = svg.attr("width") - margin.left - margin.right;
var height = svg.attr("height") - margin.top - margin.bottom;
//Plotting our base area in svg in which chart will be shown
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//X and Y scaling
var x = d3.scaleBand().rangeRound([0, width]).padding(0.4);
var y = d3.scaleLinear().rangeRound([height, 0]);
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return +d.frequency; })]);
//Final Plotting
//for x axis
g.append("g")
.call(d3.axisBottom(x))
.attr("transform", "translate(0," + height + ")");
//for y axis
g.append("g")
.call(d3.axisLeft(y))
.append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");
//for rectangles
g.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("y", function(d) { return y(d.frequency); })
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d.frequency); });
g
.selectAll(".bar")
.append("text")
.attr("dy", ".75em")
.attr("y", function(d) { return y(d.frequency); })
.attr("x", function(d) { return x(d.letter); })
.attr("text-anchor", "middle")
.text(function(d) { return y(d.frequency); });
});
</script>
</body>
</html>
RESULT:
DOM:
As, can be seen my text is added in dom per each rectangle, but cannot be seen. Pls help them being seen on top of rectangles.
The problem here is simple: you cannot append a text element inside a rect element.
The text element will show up when you inspect the DOM, but this doesn't mean that it works, and no text will be actually painted in the SVG.
So, it should be:
g.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("dy", ".75em")
.attr("y", function(d) { return y(d.frequency); })
.attr("x", function(d) { return x(d.letter); })
.attr("text-anchor", "middle")
.text(function(d) { return d.frequency; });
Note that I changed
.text(function(d) { return y(d.frequency); });
which makes no sense, to:
.text(function(d) { return d.frequency; });
Here is a demo with your code:
var data = [{
"letter": "A",
"frequency": "5.01"
}, {
"letter": "B",
"frequency": "7.80"
}, {
"letter": "C",
"frequency": "15.35"
}, {
"letter": "D",
"frequency": "22.70"
}, {
"letter": "E",
"frequency": "34.25"
}, {
"letter": "F",
"frequency": "10.21"
}, {
"letter": "G",
"frequency": "7.68"
}, ];
//Setting up of our svg with proper calculations
var svg = d3.select("body")
.append("svg").attr("width", 500).attr("height", 300);
var margin = {
top: 40,
right: 20,
bottom: 40,
left: 40
};
var width = svg.attr("width") - margin.left - margin.right;
var height = svg.attr("height") - margin.top - margin.bottom;
//Plotting our base area in svg in which chart will be shown
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//X and Y scaling
var x = d3.scaleBand().rangeRound([0, width]).padding(0.4);
var y = d3.scaleLinear().rangeRound([height, 0]);
x.domain(data.map(function(d) {
return d.letter;
}));
y.domain([0, d3.max(data, function(d) {
return +d.frequency;
})]);
//Final Plotting
//for x axis
g.append("g")
.call(d3.axisBottom(x))
.attr("transform", "translate(0," + height + ")");
//for y axis
g.append("g")
.call(d3.axisLeft(y))
.append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");
//for rectangles
g.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.letter);
})
.attr("y", function(d) {
return y(d.frequency);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.frequency);
});
g.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("dy", ".75em")
.attr("y", function(d) {
return y(d.frequency) - 16;
})
.attr("x", function(d) {
return x(d.letter) + x.bandwidth() / 2;
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.frequency;
});
<script src="https://d3js.org/d3.v4.min.js"></script>
The text element should not be inside the rect element. Just append them to your g element instead.

How to append element to div with id using d3js javascript

I am using http://d3js.org/d3.v3.min.js.
I have code that append svg to my body html element.
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 + ")");
This code append <svg> to <body>
I am new in javascript and i don't know how to write code that append this svg to my div: <div id="svg">
I try: var svg = d3.select(document.getElementById("svg")).append("svg")... but it not working.
Thank you for any help!
Edit:
There is a full code for testing
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text { font: 12px sans-serif; }
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var treeData = [
{
"name": "Top Level",
"parent": "null",
"children": [
{
"name": "Level 2: A",
"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;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.y, d.x];
});
// var svg = d3.select("div#tree").append("svg")
var svg = d3.select("#tree").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];
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function (d) {
d.y = d.depth * 180;
});
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function (d) {
return d.id || (d.id = ++i);
});
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeEnter.append("circle")
.attr("r", 10)
.style("fill", "#fff");
nodeEnter.append("text")
.attr("x", function (d) {
return d.children || d._children ? -13 : 13;
})
.attr("dy", ".35em")
.attr("text-anchor", function (d) {
return d.children || d._children ? "end" : "start";
})
.text(function (d) {
return d.name;
})
.style("fill-opacity", 1);
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function (d) {
return d.target.id;
});
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
</script>
Simply use d3.select("#svg").

How To draw bubbles on bar charts in d3.js

I am trying to draw bubbles on bar charts. On every bar there will be a bubble.That Bubbles will be generate from a different json file. Can you please provide me any suggestion. Thanks in advance.
Code below.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: #ccc;
}
.x.axis path {
display: none;
}
.node {
fill: #000;
z-index: 999;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
var svg1 = 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.tsv("data.tsv", type, function(error, data) {
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
svg1.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg1.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("Frequency");
svg1.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); })
.append("bubble")
.attr("class","bub");
var diameter = 30,
format = d3.format(",d"),
color = d3.scale.category20c();
var bubble = d3.layout.pack()
.sort(null)
.size([diameter, diameter])
.padding(1.5);
var svg = d3.select(".bub").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
d3.json("flare.json", function(error, root) {
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.packageName); });
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});
}
recurse(null, root);
return {children: classes};
}
d3.select(self.frameElement).style("height", diameter + "px");});
function type(d) {
d.frequency = +d.frequency;
return d;
}
</script>
//File for bar chart is below
data.tsv
letter frequency
A .08167
B .01492
C .02780
D .04253
//Json for bubble charts
flare.json
{
"name": "flare",
"children": [
{"name": "Swaraj", "size": 20}
]
}
I would like to display the bubble chart on bar graph.

Categories