Rotate horizontal bar chart to vertical chart - d3.js

Saw this graph on JSFiddle. I modified it with my own data, but I'd like to have a vertical bar chart instead of a horizontal. Here's what it looks like now. I tried fiddling with the X and Y axes and can't seem to get it right. Any help would be greatly appreciated.
Here's my code:
var margins = {
top: 12,
left: 48,
right: 24,
bottom: 40
},
legendPanel = {
width: 180
},
width = 400 - margins.left - margins.right - legendPanel.width,
height = 200 - margins.top - margins.bottom,
dataset = [{
data: [{
year: '2009',
count: 80
}, {
year: '2010',
count: 79
}, {
year: '2011',
count: 65
},
{
year: '2012',
count: 70
},
{
year: '2013',
count: 72
} ,
{
year: '2014*',
count: 38
}
],
name: 'Male'
}, {
data: [{
year: '2009',
count: 15
}, {
year: '2010',
count: 17
}, {
year: '2011',
count: 18
}, {
year: '2012',
count: 20
}, {
year: '2013',
count: 17
},
{
year: '2014*',
count: 8
}],
name: 'Female'
}
],
series = dataset.map(function (d) {
return d.name;
}),
dataset = dataset.map(function (d) {
return d.data.map(function (o, i) {
// Structure it so that your numeric
// axis (the stacked amount) is y
return {
y: o.count,
x: o.year
};
});
}),
stack = d3.layout.stack();
stack(dataset);
var dataset = dataset.map(function (group) {
return group.map(function (d) {
// Invert the x and y values, and y0 becomes x0
return {
x: d.y,
y: d.x,
x0: d.y0
};
});
}),
svg = d3.select('#sex')
.append('svg')
.attr('width', width + margins.left + margins.right + legendPanel.width)
.attr('height', height + margins.top + margins.bottom)
.append('g')
.attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
xMax = d3.max(dataset, function (group) {
return d3.max(group, function (d) {
return d.x + d.x0;
});
}),
xScale = d3.scale.linear()
.domain([0, xMax])
.range([0, 200]),
months = dataset[0].map(function (d) {
return d.y;
}),
_ = console.log(months),
yScale = d3.scale.ordinal()
.domain(months)
.rangeRoundBands([0, height], .1),
xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom'),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left'),
colours = d3.scale.category20c(),
groups = svg.selectAll('g')
.data(dataset)
.enter()
.append('g')
.style('fill', function (d, i) {
return colours(i);
}),
rects = groups.selectAll('rect')
.data(function (d) {
return d;
})
.enter()
.append('rect')
.attr('x', function (d) {
return xScale(d.x0);
})
.attr('y', function (d, i) {
return yScale(d.y);
})
.attr('height', function (d) {
return yScale.rangeBand();
})
.attr('width', function (d) {
return xScale(d.x);
})
.on('mouseover', function (d) {
var xPos = parseFloat(d3.select(this).attr('x')) / 2 + width / 2;
var yPos = parseFloat(d3.select(this).attr('y')) + yScale.rangeBand() / 2;
d3.select('#tooltip')
.style('left', xPos + 'px')
.style('top', yPos + 'px')
.select('#value')
.text(d.x);
d3.select('#tooltip').classed('hidden', false);
})
.on('mouseout', function () {
d3.select('#tooltip').classed('hidden', true);
})
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'axis')
.call(yAxis);
svg.append('rect')
.attr('fill', 'white')
.attr('width', 160)
.attr('height', 30 * dataset.length)
.attr('x', width + margins.left)
.attr('y', 0);
//X AXIS LABEL
svg.append("text")
.attr("class", 'x label')
.attr("y", height + 35)
.attr("x", width / 2)
.text("Victims")
.style("font-size","13px")
.style("font-weight", "600");
/*
//FOOTNOTE
svg.append("text")
.attr("class", 'x label')
.attr("y", height + 35)
.attr("x", width + 65)
.text("*As of July 2014")
.style("font-size","11px")
.style("font-style", "italic");
*/
//LEGEND
series.forEach(function (s, i) {
svg.append('text')
.attr('fill', 'black')
.attr('x', width + margins.left + 18)
.attr('y', i * 24 + 24)
.text(s);
svg.append('rect')
.attr('fill', colours(i))
.attr('width', 20)
.attr('height', 20)
.attr('x', width + margins.left + 75)
.attr('y', i * 24 + 6);
});

Related

Add space between the stacks in d3v4 stacked bar chart?

d3.json("data2.json", function(error, data) {
data.forEach(function(d) {
d.Total = +d.Total;
});
var width = 200,
height = 50;
var margin = {
top: 10,
right: 10,
bottom: 30,
left: 10
};
var svg = d3.select('body')
.append('svg')
.attr('width', '20%')
.attr('height', '20%')
.attr('viewBox', '0 0 ' + width + ' ' + height)
.append('g');
width = width - margin.left - margin.right,
height = height - margin.top - margin.bottom;
svg.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var xScale = d3.scaleLinear()
.range([0, width])
var yScale = d3.scaleBand()
.range([0, height])
.padding(0.1);
xScale.domain([0, d3.sum(data, function(d) {
return d.Total;
})]);
var x_axis = svg.append('g')
.attr('class', 'axis')
.attr('padding', 1)
.attr('transform', 'translate(' + 0 + ',' + height + ')');
var keys = data.map(function(d) {
return d.Type;
});
var newData = [{}];
data.forEach(function(d) {
newData[0][d.Type] = d.Total
});
var stack = d3.stack()
.keys(keys);
var series = stack(newData);
var colorScale = d3.scaleOrdinal()
.domain([0, 12])
.range(d3.schemeCategory10);
var bars = svg.selectAll()
.data(series)
.enter()
.append('g')
.attr('fill', function(d) {
return colorScale(d.key);
})
.selectAll('rect')
.data(function(d) {
return d;
})
.enter()
.append('rect')
.attr('x', function(d, i) {
return xScale(d[0]) ;
})
.attr('width', function(d, i) {
return xScale(d[1]) - xScale(d[0]);
})
.attr("height", yScale.bandwidth());
});
This is the code I tried. I tried adding padding to g as well as x. It does not seem to be working. I just need a horizontal single stacked bar chart along with a tooltip. I can add the tooltip later but I just need somebody to help me figure this out. I have been struggling for far too long on this. Below is the data I am using.
[
{
"Type": "Pending Review",
"Total": 3209,
"Percent": "23.90%"
},
{
"Type": "Audit Finding",
"Total": 2715,
"Percent": "20.22%"
},
{
"Type": "No Issues",
"Total": 1675,
"Percent": "12.50%"
}
]
The easiest way that I found is to subtract few pixels from the width of the bar obtained with the x-axis mapping object (xScale in your case). You can keep the positioning (x and y values) as they are. So you can just change this line:
.attr('width', function(d, i) {
return xScale(d[1]) - xScale(d[0]);
})
like this:
.attr('width', function(d, i) {
return xScale(d[1]) - xScale(d[0]) - 2;
})
The -2 do the trick.
https://codepen.io/bemipefe/pen/ExyWeYm

Stacked bar chart, y domain

I have a plunker here https://plnkr.co/edit/hBWoIIyzcHELGyewOyZE?p=preview
I'm trying to create a simple stacked bar chart.
The bars go above the top of the chart which I think is a problem with the domain
I also need a scale on the y axis which I think is to do with the y domain.
Is it the y domain that controls the height of the bars and scales shown on the y axis
y.domain([0, d3.max(data, (d)=>{
return d
})])
This is a list of the issues so far:
First, your y domain is not correctly set. It should use the stacked data:
y.domain([0, d3.max(stackedSeries, function(d) {
return d3.max(d, function(d) {
return d[0] + d[1];
});
})])
Second, the math for the y and height of the rectangles is wrong. It should be:
.attr('height', (d) => {
return y(d[0]) - y(d[0] + d[1]);
})
.attr('y', (d) => {
return y(d[0] + d[1]);
})
Finally, use the x scale for the x position:
.attr('x', (d, i) => {
return x(d.data.day)
})
Here is the code with those changes:
var margin = {
top: 40,
right: 20,
bottom: 40,
left: 40
}
var width = 400 - margin.left - margin.right
var height = 500 - margin.top - margin.bottom
var data = [{
day: 'Mon',
apricots: 120,
blueberries: 180,
cherries: 100
},
{
day: 'Tue',
apricots: 60,
blueberries: 185,
cherries: 105
},
{
day: 'Wed',
apricots: 100,
blueberries: 215,
cherries: 110
},
{
day: 'Thu',
apricots: 150,
blueberries: 330,
cherries: 105
},
{
day: 'Fri',
apricots: 120,
blueberries: 240,
cherries: 105
}
];
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 + ')')
var colors = ['#FBB65B', '#513551', '#de3163'];
var stack = d3.stack()
.keys(['apricots', 'blueberries', 'cherries']);
var stackedSeries = stack(data);
// Create a g element for each series
var g = d3.select('g')
.selectAll('g.series')
.data(stackedSeries)
.enter()
.append('g')
.classed('series', true)
.style('fill', (d, i) => {
return colors[i];
});
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1)
var y = d3.scaleLinear()
.range([height, 0])
x.domain(data.map((d) => {
return d.day
}))
y.domain([0, d3.max(stackedSeries, function(d) {
return d3.max(d, function(d) {
return d[0] + d[1];
});
})])
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + height + ')')
.call(d3.axisBottom(x))
svg.append('g')
.attr('class', 'y axis')
.call(d3.axisLeft(y))
// For each series create a rect element for each day
g.selectAll('rect')
.data((d) => {
return d;
})
.enter()
.append('rect')
.attr('height', (d) => {
return y(d[0]) - y(d[0] + d[1]);
})
.attr('y', (d) => {
return y(d[0] + d[1]);
})
.attr('x', (d, i) => {
return x(d.data.day)
})
.attr('width', x.bandwidth())
.style("stroke", "#ccc");
<script src="https://d3js.org/d3.v4.min.js"></script>

d3.js appending two labels from a dataset on the Y axis

My data for a horizontal bar graph is an array of objects that look like this:
{value: -10, dataset:"Corvette", year: "1975"}. The "dataset" labels are on the y axis. I would like to append the "year" label to the "dataset" label, so the labels on the y axis would look like this:
Corvette 1975
So far I can add one or the other to the Y axis but not both. Here is the code I have:
var margin = {top: 30, right: 10, bottom: 50, left: 50},
width = 500,
height = 300;
var data = [{value: -10, dataset:"Corvette", year: "1975"},
{value: 40, dataset:"Lumina", year: "1975"},
{value: -10, dataset:"Gran Torino", year: "1971"},
{value: -50, dataset:"Pomtiac GTO", year: "1964"},
{value: 30, dataset:"Mustang", year: "19655"},
{value: -20, dataset:"Camaro", year: "1973"},
{value: -70, dataset:"Firebird", year: "1975"}];
// Add svg to
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 + ')');
// set the ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.1);
var x = d3.scaleLinear()
.range([0, width]);
// Scale the range of the data in the domains
x.domain(d3.extent(data, function (d) {
return d.value;
}));
y.domain(data.map(function (d) {
return d.dataset;
}));
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function (d) {
return "bar bar--" + (d.value < 0 ? "negative" : "positive");
})
.attr("x", function (d) {
return x(Math.min(0, d.value));
})
.attr("y", function (d) {
return y(d.dataset);
})
.attr("width", function (d) {
return Math.abs(x(d.value) - x(0));
})
.attr("height", y.bandwidth());
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
let yAxisGroup = svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + x(0) + ",0)")
.call(d3.axisRight(y));
yAxisGroup.selectAll('.tick')
.data(data)
.select('text')
.attr('x', function(d,i){return d.value<0?9:-9})
.style('text-anchor', function(d,i){return d.value<0?'start':'end'})
Here is the fiddle:
https://jsfiddle.net/Kavitha_2817/2e1xLxLc/
You could map a concatenated string of your d.dataset and d.year to the y scale, and then use the same concatenated string when positioning your rects using that y scale.
The y axis will then use that concatenated string.
Example:
https://jsfiddle.net/2e1xLxLc/4/
Relevant code:
//create a reusable function to concatenate the values you want to use
function yValue(d) { return d.dataset + " " + d.year }
// Scale the range of the data in the domains
x.domain(d3.extent(data, function (d) {
return d.value;
}));
y.domain(data.map(function(d){ return yValue(d) }));
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function (d) {
return "bar bar--" + (d.value < 0 ? "negative" : "positive");
})
.attr("x", function (d) {
return x(Math.min(0, d.value));
})
.attr("y", function (d) {
return y(yValue(d));
})
.attr("width", function (d) {
return Math.abs(x(d.value) - x(0));
})
.attr("height", y.bandwidth());
If you (for any reason) want to keep the same domain, get the year using tickFormat:
.call(d3.axisRight(y)
.tickFormat(function(d) {
//filter the data array according to 'd', which is 'dataset'
var filtered = data.filter(function(e) {
return e.dataset === d;
})[0];
//get the year in the 'filtered' object using 'filtered.year'
return d + " " + filtered.year
})
);
Here is your code with that change:
var margin = {
top: 30,
right: 10,
bottom: 50,
left: 50
},
width = 500,
height = 300;
var data = [{
value: -10,
dataset: "Corvette",
year: "1975"
}, {
value: 40,
dataset: "Lumina",
year: "1975"
}, {
value: -10,
dataset: "Gran Torino",
year: "1971"
}, {
value: -50,
dataset: "Pomtiac GTO",
year: "1964"
}, {
value: 30,
dataset: "Mustang",
year: "19655"
}, {
value: -20,
dataset: "Camaro",
year: "1973"
}, {
value: -70,
dataset: "Firebird",
year: "1975"
}];
// Add svg to
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 + ')');
// set the ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.1);
var x = d3.scaleLinear()
.range([0, width]);
// Scale the range of the data in the domains
x.domain(d3.extent(data, function(d) {
return d.value;
}));
y.domain(data.map(function(d) {
return d.dataset;
}));
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) {
return "bar bar--" + (d.value < 0 ? "negative" : "positive");
})
.attr("x", function(d) {
return x(Math.min(0, d.value));
})
.attr("y", function(d) {
return y(d.dataset);
})
.attr("width", function(d) {
return Math.abs(x(d.value) - x(0));
})
.attr("height", y.bandwidth());
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
let yAxisGroup = svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + x(0) + ",0)")
.call(d3.axisRight(y)
.tickFormat(function(d) {
var filtered = data.filter(function(e) {
return e.dataset === d;
})[0];
return d + " " + filtered.year
})
);
yAxisGroup.selectAll('.tick')
.data(data)
.select('text')
.attr('x', function(d, i) {
return d.value < 0 ? 9 : -9
})
.style('text-anchor', function(d, i) {
return d.value < 0 ? 'start' : 'end'
})
<style> .bar--positive {
fill: steelblue;
}
.bar--negative {
fill: darkorange;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>

How to use log scale to show proper stacked bar chart using d3 JS?

I am trying to display stak chart using d3 js. I also tried with log scale but did not get to work.
Aug month staked bar not visible properly or there may be more cases like this.
How to make it visible properly using log scale?
var margins = {
top: 12,
left: 48,
right: 24,
bottom: 24
},
legendPanel = {
width: 180
},
width = 500 - margins.left - margins.right - legendPanel.width,
height = 100 - margins.top - margins.bottom,
dataset = [{
data: [{
month: 'Aug',
count: 1
}, {
month: 'feb',
count: 234
}, {
month: 'mar',
count: 345
}],
name: 'Series #1'
}, {
data: [{
month: 'Aug',
count: 3
}, {
month: 'feb',
count: 267
}, {
month: 'mar',
count: 573
}],
name: 'Series #2'
},
{
data: [{
month: 'Aug',
count: 20
}, {
month: 'feb',
count: 267
}, {
month: 'mar',
count: 573
}],
name: 'Series #3'
}
],
series = dataset.map(function (d) {
return d.name;
}),
dataset = dataset.map(function (d) {
return d.data.map(function (o, i) {
// Structure it so that your numeric
// axis (the stacked amount) is y
return {
y: o.count,
x: o.month
};
});
}),
stack = d3.layout.stack();
stack(dataset);
var dataset = dataset.map(function (group) {
return group.map(function (d) {
// Invert the x and y values, and y0 becomes x0
return {
x: d.y,
y: d.x,
x0: d.y0
};
});
}),
svg = d3.select('body')
.append('svg')
.attr('width', width + margins.left + margins.right + legendPanel.width)
.attr('height', height + margins.top + margins.bottom)
.append('g')
.attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
xMax = d3.max(dataset, function (group) {
return d3.max(group, function (d) {
return d.x + d.x0;
});
}),
xScale = d3.scale.linear()
.domain([0, xMax])
.range([0, width]),
months = dataset[0].map(function (d) {
return d.y;
}),
_ = console.log(months),
yScale = d3.scale.ordinal()
.domain(months)
.rangeRoundBands([0, height], .1),
xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom'),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left'),
colours = d3.scale.category10(),
groups = svg.selectAll('g')
.data(dataset)
.enter()
.append('g')
.style('fill', function (d, i) {
return colours(i);
}),
rects = groups.selectAll('rect')
.data(function (d) {
return d;
})
.enter()
.append('rect')
.attr('x', function (d) {
return xScale(d.x0);
})
.attr('y', function (d, i) {
return yScale(d.y);
})
.attr('height', function (d) {
return yScale.rangeBand();
})
.attr('width', function (d) {
return xScale(d.x);
})
.on('mouseover', function (d) {
var xPos = parseFloat(d3.select(this).attr('x')) / 2 + width / 2;
var yPos = parseFloat(d3.select(this).attr('y')) + yScale.rangeBand() / 2;
d3.select('#tooltip')
.style('left', xPos + 'px')
.style('top', yPos + 'px')
.select('#value')
.text(d.x);
d3.select('#tooltip').classed('hidden', false);
})
.on('mouseout', function () {
d3.select('#tooltip').classed('hidden', true);
})
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'axis')
.call(yAxis);
svg.append('rect')
.attr('fill', 'yellow')
.attr('width', 160)
.attr('height', 30 * dataset.length)
.attr('x', width + margins.left)
.attr('y', 0);
series.forEach(function (s, i) {
svg.append('text')
.attr('fill', 'black')
.attr('x', width + margins.left + 8)
.attr('y', i * 24 + 24)
.text(s);
svg.append('rect')
.attr('fill', colours(i))
.attr('width', 60)
.attr('height', 20)
.attr('x', width + margins.left + 90)
.attr('y', i * 24 + 6);
});
sample code jsfiddle
There is a built in log-scale in d3, but some more modifications are needed.
The first thing you need to do is change your xScale to be logarithmic:
xScale = d3.scale.log()
.domain([0.5, xMax])//The x-min can not be 0!
.range([0, width]),
Note that xmin is 0.5 instead of 0. Because 0 can not exist in a logarithmic scale. And putting anything larger than 1 would make the Series #1 of august not visable since it is 1.
The second thing you need is to calculate the width in a different way since your scale is not linear anymore, i.e. 10->20 is wider than 110->120:
.attr('width', function (d) {
return xScale(d.x0+d.x)- (d.x0==0 ? 0 : xScale(d.x0));
})
This simply takes the position of the end-point (d.x0+d.x) and subtract the position of the startpoint d.x0. Not that if d.x0 == 0, 0 is used as start-pos since 0 do not exist in xScale
And finaly, default is to show ticks as 1e+02 for example, so change the format for the tick by
xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(0, '.1s'),
See jsfiddle

D3 tooltip won't read my data

I am trying to make my tooltip read my data. But it won't. How do i make it read the data?
I do not understand why I can apply text labels in my chart by writing
.text(function(d) { return d; });
while the tooltip won't read it.
var data = {
labels: [
'Trøndelag', 'Innlandet', 'Oslo','Nordland','Sør-Øst', 'Alle distr.',
'Øst', 'Sør-Vest', 'Møre og R.',
'Troms', 'Vest', 'Finnmark',
],
series: [
{
label: 'Svært stor tillit',
values: [32, 29, 29, 22, 27, 27,31,25,24,26,26,20,24]
},
{
label: 'Ganske stor tillit',
values: [55,54,53,58,53,53,49,53,54,51,48,53,48]
},
{
label: 'Verken stor eller liten tillit',
values: [7,12,13,14,14,16,14,15,16,19,19,15]
},
{
label: 'Ganske liten tillit',
values: [4,4,3,2,3,3,3,3,4,5,4,4,7]
},
{
label: 'Svært liten tillit',
values: [1,1,2,3,3,2,1,3,3,1,2,4,6]
},
{
label: 'Vet ikke',
values: [0,0,1,0,0,0,1,1,0,0,0,0,1]
},
{
label: 'Ubesvart',
values: [0,0,0,0,0,0,0,0,0,0,0,0,0]
}
]
};
var margin = {top: 20, right: 5, bottom: 20, left: 5},
width = parseInt(d3.select('.chart').style('width'), 10),
width = width - margin.left - margin.right,
chartHeight = 1310,
groupHeight = barHeight * data.series.length,
gapBetweenGroups = 0,
spaceForLabels =62,
spaceForLegend = 64,
barHeight=14;
var zippedData = [];
for (var i=0; i<data.labels.length; i++) {
for (var j=0; j<data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
// Color scale
var color = d3.scale.category20c();
var x = d3.scale.linear()
.domain([0, d3.max(zippedData)])
.range([0, width]);
var y = d3.scale.linear()
.range([chartHeight + gapBetweenGroups, 0]);
d3.select(window).on('resize', resize);
function resize (){
width = parseInt(d3.select('.chart').style('width'),10);
width= width - margin.left - margin.right;
x.range([0,width]);
}
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat('')
.tickSize(0)
.orient("left");
// Specify the chart area and dimensions
var chart = d3.select(".chart")
.attr("width", spaceForLabels + width + spaceForLegend)
.attr("height", chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i/data.series.length))) + ")";
})
;
var legendPlass = 150;
var tooltip = d3.select("body")
.append("div")
.attr("class", "d3-tip")
.style("position", "absolute")
.style("opacity", 0);
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d,i) { return color(i % data.series.length); })
.attr("class", "bar")
.attr("width", x)
.attr('y', legendPlass )
.attr("height", barHeight - 1)
;
// Add text label in bar
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", legendPlass + barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
// Draw labels
bar.append("text")
.attr("class", "label")
.attr("x", function(d) { return - 5; })
.attr("y", legendPlass)
.attr("dy", "1em")
.text(function(d,i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i/data.series.length)];
else
return ""});
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups/2 + ")")
.call(yAxis);
//CREATING THE TOOLTIP
chart.selectAll(".bar")
.on("click", function() {
tooltip.style("opacity", 0); })
.on("click", function(d) {
var pos = d3.mouse(this);
tooltip
.transition()
.duration(500)
.style("opacity", 1)
.style("left", d3.event.x + "px")
.style("top", d3.event.y + "px")
.text(function(d) { return d; });
});
// Draw legend
var legendRectSize = 16,
legendSpacing = 4;
var legend = chart.selectAll('.legend')
.data(data.series)
.enter()
.append('g')
.attr('transform', function (d, i) {
var height = legendRectSize + legendSpacing;
var offset = -gapBetweenGroups/2;
var horz = spaceForLegend;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', function (d, i) { return color(i); })
.style('stroke', function (d, i) { return color(i); });
legend.append('text')
.attr('class', 'legend')
.attr('x', legendRectSize + legendSpacing )
.attr('y', legendRectSize - legendSpacing)
.text(function (d) { return d.label; });
You need to append data to it to be able to read. You have this :
var tooltip = d3.select("body")
.append("div")
.attr("class", "d3-tip")
.style("position", "absolute")
.style("opacity", 0);
Needs to be like this :
var tooltip = d3.select("body")
.append("div")
.attr("class", "d3-tip")
.style("position", "absolute")
.style("opacity", 0);
var tooltipWithData = tooltip.data(data).enter();
Then use this later :
tooltipWithData
.transition()
.duration(500)
.style("opacity", 1)
.style("left", d3.event.x + "px")
.style("top", d3.event.y + "px")
.text(function(d) { return d; });

Resources