Add labels to bar chart D3 - d3.js

I'm trying to add labels to my bar chart, and I can't make it work. I read a lot about it and tried many things already, but no success.
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%Y-%m");
var x = d3.scaleBand().rangeRound([0, width]).paddingInner(0.05);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%Y-%m"));
var yAxis = d3.axisLeft(y)
.ticks(10);
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("bar-data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
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("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.date); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
});
Here is my Plunker.
Any help is appreciated. Thank you in advance.

You can add labels to the bars using the snippet below -
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("class","label")
.attr("x", (function(d) { return x(d.date); } ))
.attr("y", function(d) { return y(d.value) - 20; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
Your problem was here. The correct approach to get x-y positions for the labels would be the same approach you used for the bars using the x and y variables.
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
Updated Plunkr - https://plnkr.co/edit/e6HPuph3OSbpxeEVQXfF?p=preview

Related

Rotate label text of bar chart by 90deg

How to rotate text of label of barchart in d3.js? I tried using
.attr("transform", "rotate(-90)") but it rotates the entire column.
csv file:
date,value
2013-01,53
2013-02,165
2013-03,269
2013-04,344
2013-05,376
2013-06,410
2013-07,421
2013-08,405
2013-09,376
2013-10,359
2013-11,392
2013-12,433
2014-01,455
2014-02,478
code:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
// Code goes here
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
padding = -60; // space around the chart, not including labels
// Parse the date / time
var parseDate = d3.timeParse("%Y-%m");
var x = d3.scaleBand().rangeRound([0, width]).paddingInner(0.05);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%Y-%m"));
var yAxis = d3.axisLeft(y)
.ticks(10);
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("bar-data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
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("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.date); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
//.attr("transform", "rotate(-90)")
.attr("x", (function(d) { return x(d.date); } ))
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.value); })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
});
// now add titles to the axes
svg.append("text")
.attr("text-anchor", "middle") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate("+ (padding/2) +","+(height/2)+")rotate(-90)") // text is drawn off the screen top left, move down and out and rotate
.text("Value");
svg.append("text")
.attr("text-anchor", "middle") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate("+ (width/2) +","+(height-(padding))+")") // centre below axis
.text("Date");
</script>
</body>
</html>
What you see is actually the expected behaviour, since the rotate function of the transform attribute rotates all the elements around their origins, not around their centres.
The easiest solution is passing the optional x and y arguments to rotate:
.attr("transform", function(d) {
return "rotate(-90," + x(d.date) + "," + y(d.value) + ")";
//x and y here ------------^------------------^
})
Here is your code with that change:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
// Code goes here
var csv = `date,value
2013-01,53
2013-02,165
2013-03,269
2013-04,344
2013-05,376
2013-06,410
2013-07,421
2013-08,405
2013-09,376
2013-10,359
2013-11,392
2013-12,433
2014-01,455
2014-02,478`;
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
padding = -60; // space around the chart, not including labels
// Parse the date / time
var parseDate = d3.timeParse("%Y-%m");
var x = d3.scaleBand().rangeRound([0, width]).paddingInner(0.05);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%Y-%m"));
var yAxis = d3.axisLeft(y)
.ticks(10);
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 data = d3.csvParse(csv);
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
x.domain(data.map(function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.value;
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
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("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) {
return x(d.date);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("transform", function(d) {
return "rotate(-90," + x(d.date) + "," + y(d.value) + ")";
})
.attr("x", (function(d) {
return x(d.date);
}))
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("dy", "1.3em")
.attr("dx", "0.2em")
.text(function(d) {
return d.value;
});
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
// now add titles to the axes
svg.append("text")
.attr("text-anchor", "middle") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate(" + (padding / 2) + "," + (height / 2) + ")rotate(-90)") // text is drawn off the screen top left, move down and out and rotate
.text("Value");
svg.append("text")
.attr("text-anchor", "middle") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate(" + (width / 2) + "," + (height - (padding)) + ")") // centre below axis
.text("Date");
</script>
</body>
</html>

Add labels under every bar of the grouped bar chart on D3

I'm relatively new to D3 and trying to add labels to a grouped bar chart.. With below implementation, I'm only able to see them under one group instead of both.
Below is how the data looks in the db:
category,Exceed,Fully Meets,Partially Meets,Does not meet
business,10,20,30,30
leadership,15,5,30,50
Below is the code:
var chart1 = d3.select("#svgarea2"),
margin = { top: 70, right: 0, bottom: 30, left: 40 },
width = +chart1.attr("width") - margin.left - margin.right,
height = +chart1.attr("height") - margin.top - margin.bottom,
g = chart1.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//chart background color
var bg = d3.select("g").append("svg")
// .attr("width", width + margin.right + margin.left)
.attr("width", 510 + "px")
// .attr("height", height + margin.top + margin.bottom);
.attr("height", 310 + "px");
bg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "#f8f8ff");
bg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//scale chart
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.4);
var x1 = d3.scaleBand()
.padding(0.05);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal() //d3.schemeCategory20
// .range(["#0000ff", "#dcdcdc", "#696969", "#00008b"]);
.range(["#00008b", "#696969", "#dcdcdc", "#0000ff"]);
var columns = ['category', 'Does Not Meet', 'Partially Meets', 'Fully Meets', 'Exceed'];
var keys = columns.slice(1);
var color = d3.scaleOrdinal()
.range(["#00008b", "#696969", "#dcdcdc", "#0000ff"]);
x0.domain(data.map(function (d) { return d.category; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, 100]).nice();
g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function (d) { return "translate(" + x0(d.category) + ",0)"; })
.selectAll("rect")
.data(function (d) { return keys.map(function (key) { return { key: key, value: d[key] }; }); })
.enter().append("rect")
.attr("x", function (d) { return x1(d.key); })
.attr("y", function (d) {
return y(d.value);
})
.attr("width", x1.bandwidth() - 7)
.attr("height", function (d) { return height - y(d.value); })
.attr("fill", function (d) { return z(d.key); })
.on("mousemove", function(d){
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((d.key) + "<br>" + (d.value) + "%");
});
g.append("g")
.selectAll("g")
.data(data).enter()
.append("g")
.attr("transform", function (d) { return keys })
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.attr("x", function (d) { return x0(d.category); })
.call(d3.axisBottom(x1))
.selectAll("text")
.attr("y", 15)
.attr("x", 0)
.attr("dy", ".35em")
.attr("transform", "rotate(50)")
.style("text-anchor", "start");;
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) - 5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
.text("Employees (%)");
//chart title
g.append("text")
.attr("x", (width / 2) + 30)
.attr("y", 1 - (margin.top / 2) + 20)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("font-weight", "bold")
.style("text-decoration", "underline")
.attr("font-family", "sans-serif")
.text("Performance Distribution");
};
Any help is appreciated!
It will work if you create a g element for each barchart, and then add you axes, bars etc to each. See here for example:
http://blockbuilder.org/tomshanley/aa5471a3ecaf9e41283d68188aecf042
Relevant code:
var chart = g.append("g")
.selectAll("g")
.data(data)
.enter().append("g");
chart.attr("transform", function (d) { return "translate(" + x0(d.category) + ",0)"; })
.selectAll("rect")
.data(function (d) { return keys.map(function (key) { return { key: key, value: d[key] }; }); })
.enter().append("rect")
.attr("x", function (d) { return x1(d.key); })
.attr("y", function (d) {
return y(d.value);
})
.attr("width", x1.bandwidth() - 7)
.attr("height", function (d) { return height - y(d.value); })
.attr("fill", function (d) { return z(d.key); })
//APPEND AN AXIS TO THE CHART G'S
chart.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.attr("x", function (d) { return x0(d.category); })
.call(d3.axisBottom(x1))
.selectAll("text")
.attr("y", 15)
.attr("x", 0)
.attr("dy", ".35em")
.attr("transform", "rotate(50)")
.style("text-anchor", "start");

In d3.js ticks are not showing in the x axis

I am trying to show a barchart using d3.js. Y axis contains the speed and x axis contains time. I am using the following code:
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 400 - margin.left - margin.right,
height = 250 - margin.top;
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").ticks(20);
x.domain(data.map(function(d) { return d.datetime; }));
y.domain([0, d3.max(data, function(d) { return d.speed; })]);
var svg=d3.select("#bar").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 transition = svg.transition().duration(750), delay = function(d, i) {
return i * 50;
};
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" ).text("Time");
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("Speed");
svg.selectAll("rect")
.data(data)
.enter().append("rect").transition().delay(0)
.style("fill", "red")
.attr("x", function(d,i) { return 30*i+20; })
.attr("width", 25)
.attr("y", function(d) { return y(d.speed); })
.attr("height", function(d) { return height - y(d.speed); }); //function(d){return " "+d.datetime;}
transition.select(".y.axis").call(yAxis);
But unfortunately no ticks are showing in the x axis. Y axis ticks are working fine. Can anyone help me regarding this?
In your x-axis creation, this:
.attr("transform", "rotate(-90)" ).text("Time");
is just going to but the word "Time" on each tick. What you need is:
// define the time format you want
var format = d3.time.format("%Y-%m-%d");
// create x axis
...
.text(function(d){
return format(d);
});
Also in your rect placement:
svg.selectAll("rect")
...
.attr("x", function(d,i) { return 30*i+20; })
You are spacing them based on index. You need to match this to the axis position:
svg.selectAll("rect")
...
.attr("x", function(d, i) {
return x(d.datetime);
})
Here's an example.
Your problem may be where you set the domain for x:
x.domain(data.map(function(d) { return d.datetime; }));
You probably want something like:
x.domain([d3.min(data, function(d) { return d.datetime; }), d3.max(data, function(d) { return d.datetime; })]);

D3 toggle stacked to grouped on multiple bar charts

I'm trying to run multiple "stacked-to-grouped" d3 bar charts on one page. I can get the charts to render, but have not been successful in getting the two charts to toggle between the options in unison.
I'm guessing that this might have to do with calling the "change" function more than once (since I'm calling it in the rendering of both charts), but I'm not sure how to place it outside of the charts and enable it to have access to what it needs. Thought it might have something to do with "each", but I'm not sure.
Here's a link to the jsfiddle that I've created: http://jsfiddle.net/1amsknh2/
And here's the js for the charts:
$( document ).ready(function() {
chart1();
});
function chart1(){
var stack = d3.layout.stack(),
layers = [
[
{"x":0,"y":1.5,"y0":0,"name":"cat1","color":"#B7A4DB"},
{"x":1,"y":1.5,"y0":0,"name":"cat2","color":"#B7A4DB"},
{"x":2,"y":1.5,"y0":0,"name":"cat3","color":"#B7A4DB"}
],
[
{"x":0,"y":2.5,"y0":1.5,"name":"cat1","color":"#85E6B5"},
{"x":1,"y":1.5,"y0":1.5,"name":"cat2","color":"#85E6B5"},
{"x":2,"y":1.0,"y0":1.5,"name":"cat3","color":"#85E6B5"}
]
];
n = 2, // number of layers
m = layers.length, // number of samples per layer
mb = ['cat1', 'cat2', 'cat3']
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var margin = {top: 40, right: 10, bottom: 20, left: 40},
width = 400 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(mb)
.rangeRoundBands([0, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart1").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 layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer");
// .style("fill", function(d) { return x(d.color); });
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0)
.style("fill", function(d) { return d.color; });
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Amount");
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
console.log(1)
if (this.value === "grouped") transitionGrouped();
else transitionStacked();
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Contribution Amount");
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) { return x(d.name) + x.rangeBand() / n * j; })
.attr("width", x.rangeBand() / n)
.transition()
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); });
}
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand());
}
chart2();
}
function chart2(){
var stack = d3.layout.stack(),
layers = [
[
{"x":0,"y":0.5,"y0":0,"name":"cat1","color":"#B7A4DB"},
{"x":1,"y":1.5,"y0":0,"name":"cat2","color":"#B7A4DB"},
{"x":2,"y":1.0,"y0":0,"name":"cat3","color":"#B7A4DB"}
],
[
{"x":0,"y":2.5,"y0":0.5,"name":"cat1","color":"#85E6B5"},
{"x":1,"y":1.5,"y0":1.5,"name":"cat2","color":"#85E6B5"},
{"x":2,"y":1.0,"y0":1.0,"name":"cat3","color":"#85E6B5"}
]
];
n = 2, // number of layers
m = layers.length, // number of samples per layer
mb = ['cat1', 'cat2', 'cat3']
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var margin = {top: 40, right: 10, bottom: 20, left: 40},
width = 400 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(mb)
.rangeRoundBands([0, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart2").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 layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0)
.style("fill", function(d) { return d.color; });
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Contribution Amount");
d3.selectAll("input").on("change", change);
function change() {
console.log(2);
if (this.value === "grouped") transitionGrouped();
else transitionStacked();
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Amount");
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) { return x(d.name) + x.rangeBand() / n * j; })
.attr("width", x.rangeBand() / n)
.transition()
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); });
}
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand());
}
}
After struggling here and there, finally I made one fiddle for you.check it once.I hope you are looking for this http://jsfiddle.net/jxbyf82u/
In this fiddle Observe these line
d3.selectAll("input").on("change", change1);
chart1.change1 = change1;
and I'm calling this function from chart2()'s change() function by passing input value i.e. like below
chart1.change1(this.value);
If it is not what you are looking for, then ask what you want.Okay

d3.js line chart with negative numbers

I have a working d3.js line chart that renders linear numbers: http://jsfiddle.net/2g9VQ/
var probArray = ["1.0", "0.999999931839", "0.999816434171", "0.994147880224", "0.961785353466", "0.882923015661", "0.763731336472", "0.627901360001", "0.497594590727", "0.385100568858", "0.256161790111", "0.168894610653", "0.111773057", "0.0747467808441", "0.051065424573", "0.0355360834346", "0.0251527408762", "0.018097770"];
var imlArray = ["2.0", "4.0", "6.0", "8.0", "10.0", "12.0", "14.0", "16.0", "18.0", "20.0", "23.0", "26.0", "29.0", "32.0", "35.0", "38.0", "41.0", "44.0", "47.0", "50.0", "55.0", "60.0", "65.0", "70.0", "75.0", "80.0", "85.0", "90.0", "95.0", "100.0", "110.0", "120.0", "130.0", "140.0", "150.0", "160.0", "170.0", "180.0", "190.0", "200.0", "220.0", "240.0", "260.0", "280.0", "300.0"];
function log(n) {
return Math.log(n) / Math.LN10;
}
var data = [];
for(i=0; i<probArray.length; i++) {
// without log values...
data.push([parseFloat(imlArray[i]), parseFloat(probArray[i])]);
// with log valuse...
//data.push([log(parseFloat(imlArray[i])), log(parseFloat(probArray[i]))]);
}
console.log(data);
var margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 400 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
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");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var svg = d3.select("#dialog").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 dataCallback = function(d) {
d.x = +d[0];
d.y = +d[1];
};
data.forEach(dataCallback);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 160)
.attr("y", 30)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Intensity measure type");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -50)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Probabability of exceedance in "+invest_time+" years");
var legend = d3.select("#dialog").append("svg");
legend.append("text")
.attr("x", 20)
.attr("y", 7)
.attr("dy", ".35em")
.text("Location (Lon/Lat): "+lng+", "+lat);
d3.select('#chart').on("click", function() {
data.splice(0,1);
data.push([5,5]);
dataCallback(data[data.length - 1]);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.selectAll("path").data([data])
.attr("d", line);
});
But the chart fails to render when I change the points to a logarithmic scale: http://jsfiddle.net/Z3Yms/
var probArray = ["1.0", "0.999999931839", "0.999816434171", "0.994147880224", "0.961785353466", "0.882923015661", "0.763731336472", "0.627901360001", "0.497594590727", "0.385100568858", "0.256161790111", "0.168894610653", "0.111773057", "0.0747467808441", "0.051065424573", "0.0355360834346", "0.0251527408762", "0.018097770"];
var imlArray = ["2.0", "4.0", "6.0", "8.0", "10.0", "12.0", "14.0", "16.0", "18.0", "20.0", "23.0", "26.0", "29.0", "32.0", "35.0", "38.0", "41.0", "44.0", "47.0", "50.0", "55.0", "60.0", "65.0", "70.0", "75.0", "80.0", "85.0", "90.0", "95.0", "100.0", "110.0", "120.0", "130.0", "140.0", "150.0", "160.0", "170.0", "180.0", "190.0", "200.0", "220.0", "240.0", "260.0", "280.0", "300.0"];
function log(n) {
return Math.log(n) / Math.LN10;
}
var data = [];
for(i=0; i<probArray.length; i++) {
// without log values...
//data.push([parseFloat(imlArray[i]), parseFloat(probArray[i])]);
// with log valuse...
data.push([log(parseFloat(imlArray[i])), log(parseFloat(probArray[i]))]);
}
console.log(data);
var margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 400 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
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");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var svg = d3.select("#dialog").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 dataCallback = function(d) {
d.x = +d[0];
d.y = +d[1];
};
data.forEach(dataCallback);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 160)
.attr("y", 30)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Intensity measure type");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -50)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Probabability of exceedance in "+invest_time+" years");
var legend = d3.select("#dialog").append("svg");
legend.append("text")
.attr("x", 20)
.attr("y", 7)
.attr("dy", ".35em")
.text("Location (Lon/Lat): "+lng+", "+lat);
d3.select('#chart').on("click", function() {
data.splice(0,1);
data.push([5,5]);
dataCallback(data[data.length - 1]);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.selectAll("path").data([data])
.attr("d", line);
});
I believe this is due to the numbers becoming negative along the y axis.
You were setting the domain of the y axis as
y.domain([0, d3.max(data, function(d) { return d.y; })]);
which with the log values won't work because all values are less than 0. To fix, simply use
y.domain(d3.extent(data, function(d) { return d.y; }));
instead. You also might want to use a linear scale instead of a time scale for the x axis. Complete jsfiddle here.

Resources