multi/grouped Bar chart using D3 alignment issue - javascript

I am creating a grouped bar chart using D3. I have written code and bar charts are showing but not properly. Some bar are going below the x-axis and other are at the top of the graph instead starting from 0. I am unable to figure out the reason for the this issue.
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var z = d3.scale.category20c();
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 parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ");
var data = [{
"data": [
[
"2016-01-21T01:20:00.000Z",
1.41818181818182
],
[
"2016-01-21T02:28:00.000Z",
1.90661764705882
],
[
"2016-01-21T03:36:00.000Z",
1.66764705882353
],
[
"2016-01-21T04:44:00.000Z",
1.51691176470588
],
[
"2016-01-21T05:52:00.000Z",
1.40955882352941
],
[
"2016-01-21T07:00:00.000Z",
1.46323529411765
],
[
"2016-01-21T08:08:00.000Z",
1.48308823529412
],
[
"2016-01-21T09:16:00.000Z",
1.89384615384615
]
],
"label": "a"
}, {
"data": [
[
"2016-01-21T01:20:00.000Z",
4.98701298701299
],
[
"2016-01-21T02:28:00.000Z",
5.0
],
[
"2016-01-21T03:36:00.000Z",
4.94852941176471
],
[
"2016-01-21T04:44:00.000Z",
4.91176470588235
],
[
"2016-01-21T05:52:00.000Z",
4.81617647058824
],
[
"2016-01-21T07:00:00.000Z",
5.0
],
[
"2016-01-21T08:08:00.000Z",
4.94117647058824
],
[
"2016-01-21T09:16:00.000Z",
4.96969696969697
]
],
"label": "b"
}];
var x = d3.scale.ordinal().rangeRoundBands([0, width], .9);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x).tickSize(0)
.orient("bottom").innerTickSize(-height).outerTickSize(0)
.tickFormat(d3.time.format("%H:%M"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left").innerTickSize(-width).outerTickSize(0);
var ary = [];
data.forEach(function(d) {
ary.push(d.data);
});
x.domain(ary[0].map(function(d) {
return parseDate.parse(d[0]);
}));
y.domain([0, d3.max(d3.merge(ary), function(d) {
console.log(d.y0 + d.y); //This is NaN = Not a number
//return d.y0 + d.y;
return d[1]; //returns grid lines if that is what you want
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var layer = svg.selectAll(".layer")
.data(data)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) {
return z(i);
});
layer.selectAll("rect")
.data(function(d) {
return d.data;
})
.enter().append("rect")
.attr("x", function(d) {
return x(parseDate.parse(d[0]));
})
.attr("y", function(d) {
console.log(d[1]);
return y(d[1]); //Note this is returning data
})
.attr("height", function(d) {
return y(d[1]); //Note this is returning data
})
.attr("width", x.rangeBand() - 1);
text.inner-circle {
font-weight: 400;
font-size: 12px;
text-transform: uppercase;
}
text.inner-text {
font-weight: 400;
font-size: 36px;
font-family: 'Metric Regular', 'Metric';
text-align: center;
font-style: normal;
text-transform: uppercase;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 2;
shape-rendering: crispEdges;
}
.grid .tick {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Please help me fix this issue.

You are missing this:
.attr("y", function(d) {
return height - y(d[1]); //<-- offset y position from height
})
In addition, you aren't taking into account where to group your bars. Simple fix is to place them side-by-side:
...
.enter().append("rect")
.attr("x", function(d, i, j) {
// j is the group
if (j === 0)
return x(parseDate.parse(d[0])) - x.rangeBand() / 2;
else
return x(parseDate.parse(d[0])) + x.rangeBand() / 2;
})
...
Full Code:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<style>
text.inner - circle {
font - weight: 400;
font - size: 12 px;
text - transform: uppercase;
}
text.inner - text {
font - weight: 400;
font - size: 36 px;
font - family: 'Metric Regular', 'Metric';
text - align: center;
font - style: normal;
text - transform: uppercase;
}
path {
stroke: steelblue;
stroke - width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke - width: 2;
shape - rendering: crispEdges;
}
.grid.tick {
stroke: lightgrey;
stroke - opacity: 0.7;
shape - rendering: crispEdges;
}
.grid path {
stroke - width: 0;
}
</style>
</head>
<body>
<script>
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var z = d3.scale.category20c();
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 parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ");
var data = [{
"data": [
[
"2016-01-21T01:20:00.000Z",
1.41818181818182
],
[
"2016-01-21T02:28:00.000Z",
1.90661764705882
],
[
"2016-01-21T03:36:00.000Z",
1.66764705882353
],
[
"2016-01-21T04:44:00.000Z",
1.51691176470588
],
[
"2016-01-21T05:52:00.000Z",
1.40955882352941
],
[
"2016-01-21T07:00:00.000Z",
1.46323529411765
],
[
"2016-01-21T08:08:00.000Z",
1.48308823529412
],
[
"2016-01-21T09:16:00.000Z",
1.89384615384615
]
],
"label": "a"
}, {
"data": [
[
"2016-01-21T01:20:00.000Z",
4.98701298701299
],
[
"2016-01-21T02:28:00.000Z",
5.0
],
[
"2016-01-21T03:36:00.000Z",
4.94852941176471
],
[
"2016-01-21T04:44:00.000Z",
4.91176470588235
],
[
"2016-01-21T05:52:00.000Z",
4.81617647058824
],
[
"2016-01-21T07:00:00.000Z",
5.0
],
[
"2016-01-21T08:08:00.000Z",
4.94117647058824
],
[
"2016-01-21T09:16:00.000Z",
4.96969696969697
]
],
"label": "b"
}];
var x = d3.scale.ordinal().rangeRoundBands([0, width], .9);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x).tickSize(0)
.orient("bottom").innerTickSize(-height).outerTickSize(0)
.tickFormat(d3.time.format("%H:%M"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left").innerTickSize(-width).outerTickSize(0);
var ary = [];
data.forEach(function(d) {
ary.push(d.data);
});
x.domain(ary[0].map(function(d) {
return parseDate.parse(d[0]);
}));
y.domain([0, d3.max(d3.merge(ary), function(d) {
console.log(d.y0 + d.y); //This is NaN = Not a number
//return d.y0 + d.y;
return d[1]; //returns grid lines if that is what you want
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var layer = svg.selectAll(".layer")
.data(data)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) {
return z(i);
});
layer.selectAll("rect")
.data(function(d) {
return d.data;
})
.enter().append("rect")
.attr("x", function(d, i, j) {
if (j === 0)
return x(parseDate.parse(d[0])) - x.rangeBand() / 2;
else
return x(parseDate.parse(d[0])) + x.rangeBand() / 2;
})
.attr("y", function(d) {
return height -y(d[1]); //Note this is returning data
})
.attr("height", function(d) {
return y(d[1]); //Note this is returning data
})
.attr("width", x.rangeBand() - 1);
</script>
</body>
</html>

Related

Set custom tick value on d3v4 bat charts from JSON data

I am trying to get values from a JSON File and use them as the X and Y axis on a d3 v4 bar chart. But my axis is not showing up as I like. WHat am I doing wrong?
My HTML Code:
<div class="col" id="main-chart" style="padding-top:75px;">
<svg width="675" height="415"></svg>
</div>
My D3 Code:
var svg = d3.select("#main-chart svg"),
margin = {top: 20, right: 20, bottom: 30, left: 75},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var tooltip = d3.select("body").append("div").attr("class", "toolTip");
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var colours = d3.scaleOrdinal().range(["#6F257F", "#CA0D59"]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json(data.json, function(error, data) {
if (error) throw error;
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.values; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
// .attr("transform", "rotate(-90deg)")
.call(d3.axisBottom(x).ticks(5));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(5).tickFormat(function(d) {return parseInt(d); }).tickSizeInner([-width]))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.attr("fill", "#5D6971");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("x", function(d) {return x(d.date); })
.attr("y", function(d) {return y(d.values); })
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d.values); })
.attr("fill", function(d) { return colours(d.date); })
.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.date) + "<br>" + (d.values));
})
.on("mouseout", function(d){ tooltip.style("display", "none");});
});
My JSON CODE:
[
{
"date": "2018-10-19",
"values": 6574406
},
{
"date": "2018-10-20",
"values": 6575406
},
{
"date": "2018-10-21",
"values": 6575696
},
{
"date": "2018-10-22",
"values": 6576656
},
{
"date": "2018-10-23",
"values": 6577222
},
{
"date": "2018-10-24",
"values": 6578908
},
{
"date": "2018-10-25",
"values": 6579386
},
{
"date": "2018-10-26",
"values": 6580020
},
{
"date": "2018-10-27",
"values": 6580214
},
{
"date": "2018-10-28",
"values": 6580440
},
{
"date": "2018-10-29",
"values": 6581334
},
{
"date": "2018-10-30",
"values": 6583556
},
{
"date": "2018-10-31",
"values": 6584098
},
{
"date": "2018-11-01",
"values": 6584660
}
]
My chart looks smushed and I want my Y-Axis to start with the lowest value. Which in this case is 6574406 and want to increment by 25 with 10 ticks. I have tried many variations but am not able to get the x-axis un-overlapped. I tried to skew the values but that did not work either.
My chart:

D3 v3 - String values as x-axis domain for stacked chart not working

I have been struggling to get this chart work. I tried so many methods. It didn't show any error but doesn't draw the chart properly.
I want to use strings as x axis domain. I had even tried to set domain for x-scale. Still no use. The code which I have tried so far:
$(".wrapper").delay(600).fadeIn(500);
var barDataset = [{
"name": "aA",
"date": 1,
"successful": 1,
"unsuccessful": 2
},
{
"name": "bB",
"date": 2,
"successful": 41,
"unsuccessful": 8
},
{
"name": "cC",
"date": 3,
"successful": 44,
"unsuccessful": 4
},
{
"name": "dD",
"date": 4,
"successful": 2,
"unsuccessful": 5
},
{
"name": "eE",
"date": 5,
"successful": 21,
"unsuccessful": 1
},
{
"name": "fF",
"date": 6,
"successful": 14,
"unsuccessful": 6
},
{
"name": "gG",
"date": 7,
"successful": 42,
"unsuccessful": 1
},
{
"name": "hH",
"date": 8,
"successful": 10,
"unsuccessful": 1
},
{
"name": "iI",
"date": 9,
"successful": 24,
"unsuccessful": 10
},
{
"name": "jJ",
"date": 10,
"successful": 23,
"unsuccessful": 6
},
{
"name": "kK",
"date": 11,
"successful": 21,
"unsuccessful": 15
},
{
"name": "lL",
"date": 12,
"successful": 28,
"unsuccessful": 15
}
]
function drawBarGraph(data) {
var status = ["successful", "unsuccessful"];
var colors = [
["Successful", "#50E3C2"],
["Unsuccessful", "#EF5C6E"]
];
var margin = {
top: 30,
right: 30,
bottom: 40,
left: 60
},
width = 860 - margin.left - margin.right,
height = 290 - margin.top - margin.bottom;
var z = d3.scale.ordinal()
.range(["#50E3C2", "#EF5C6E"]);
/* var n = 12;
var x = d3.scale.linear()
.domain([1, n - 1])
.rangeRound([0, width], .1);*/
var x = d3.scale.ordinal()
.domain(data.map(function(d) {
return d['name'];
}))
.rangeRoundBands([0, width], .5);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
/*.tickFormat(d3.format("d"))
.ticks(30)*/
;
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickFormat(d3.format("d"));
var svg = d3.select("#chart-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 layers = d3.layout.stack()
(status.map(function(c) {
return data.map(function(d) {
return {
x: d.date,
y: d[c]
};
});
}));
y.domain([
0, d3.max(layers[layers.length - 1], function(d) {
return d.y0 + d.y;
})
]);
// gridlines in y axis function
function make_y_gridlines() {
return d3.svg.axis().scale(y)
.orient("left").ticks(5);
}
// add the Y gridlines
svg.append("g")
.attr("class", "gridline")
.call(make_y_gridlines()
.tickSize(-width)
.tickFormat("")
);
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(6," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "translate(364,0)")
.attr("y", "3em")
.style("text-anchor", "middle")
.text("Days");
svg.append("g")
.attr("class", "axis axis--y")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("x", "-5em")
.attr("y", "-2.5em")
.style("text-anchor", "end")
.text("Number of calls sent");
function type(d) {
// d.date = parseDate(d.date);
d.date;
status.forEach(function(c) {
d[c] = +d[c];
});
return d;
}
var tooltip = d3.select("#chart-bar").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) {
return z(i);
});
layer.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html("<span>" + d.y + " calls" + "</span>")
.style("left", (d3.event.pageX - 25) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("x", function(d) {
return x(d.x);
})
.attr("y", function(d) {
return height;
})
.attr("width", 12)
.attr("height", 0)
.transition().duration(1500)
.attr("y", function(d) {
return y(d.y + d.y0);
})
.attr("height", function(d) {
return y(d.y0) - y(d.y + d.y0);
});
}
drawBarGraph(barDataset);
$('.count').each(function() {
$(this).prop('Counter', 0).animate({
Counter: $(this).text()
}, {
duration: 1500,
easing: 'swing',
step: function(now) {
$(this).text(Math.ceil(now));
}
});
});
#import url("https://fonts.googleapis.com/css?family=Overpass");
* {
box-sizing: border-box;
font: normal 14px/1.5 "Overpass", sans-serif;
}
body {
background: #76daff;
}
.chart-wrapper {
background: #333B66;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
clear: both;
padding: 20px 0 10px;
}
text {
font-size: 12px;
fill: #A7B2EB;
}
.axis path,
.axis line,
.gridline line {
fill: none;
stroke: #fff;
opacity: 0.1;
shape-rendering: crispEdges;
}
.line {
stroke: #17EAD9;
stroke-width: 3px;
fill: none;
}
path.domain {
fill: none;
opacity: 0.1;
}
div.tooltip {
color: #4a4a4a;
position: absolute;
text-align: center;
padding: 3px 6px;
font-size: 12px;
background: #fff;
border-radius: 4px;
pointer-events: none;
}
.tick text {
font-size: 10px;
}
.vbroadcast-legend {
float: right;
margin-right: 40px;
margin-top: 16px;
}
.vbroadcast-legend li {
color: #fff;
font-size: 13px;
float: left;
list-style: none;
margin-left: 20px;
padding-left: 18px;
position: relative;
}
.vbroadcast-legend li:before {
content: "";
height: 12px;
left: 0;
position: absolute;
top: 3px;
width: 12px;
}
.vbroadcast-legend li.successful:before {
background: #50e3c2;
}
.vbroadcast-legend li.unsuccessful:before {
background: #ef5c6e;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart-bar" class="chart-wrapper"></div>
Kindly help me in fixing it. Thanks in advance.
Thanks for getting back with the data. It's a minor fix in your code.
You're using name for drawing the X axis but it's not being mapped while being assigned to the layers array.
Relevant changes:
Changed d.date to d.name
return data.map(function(d) {
return {
x: d.name,
y: d[c]
};
});
Assigning x to the rects using this d.x and axes rangeBand to align it with the ticks.
.attr("x", function(d) {
return x(d.x) + x.rangeBand()/2;
})
Snippet:
$(".wrapper").delay(600).fadeIn(500);
var barDataset = [{
"name": "aA",
"date": 1,
"successful": 1,
"unsuccessful": 2
},
{
"name": "bB",
"date": 2,
"successful": 41,
"unsuccessful": 8
},
{
"name": "cC",
"date": 3,
"successful": 44,
"unsuccessful": 4
},
{
"name": "dD",
"date": 4,
"successful": 2,
"unsuccessful": 5
},
{
"name": "eE",
"date": 5,
"successful": 21,
"unsuccessful": 1
},
{
"name": "fF",
"date": 6,
"successful": 14,
"unsuccessful": 6
},
{
"name": "gG",
"date": 7,
"successful": 42,
"unsuccessful": 1
},
{
"name": "hH",
"date": 8,
"successful": 10,
"unsuccessful": 1
},
{
"name": "iI",
"date": 9,
"successful": 24,
"unsuccessful": 10
},
{
"name": "jJ",
"date": 10,
"successful": 23,
"unsuccessful": 6
},
{
"name": "kK",
"date": 11,
"successful": 21,
"unsuccessful": 15
},
{
"name": "lL",
"date": 12,
"successful": 28,
"unsuccessful": 15
}
]
function drawBarGraph(data) {
var status = ["successful", "unsuccessful"];
var colors = [
["Successful", "#50E3C2"],
["Unsuccessful", "#EF5C6E"]
];
var margin = {
top: 30,
right: 30,
bottom: 40,
left: 60
},
width = 860 - margin.left - margin.right,
height = 290 - margin.top - margin.bottom;
var z = d3.scale.ordinal()
.range(["#50E3C2", "#EF5C6E"]);
/* var n = 12;
var x = d3.scale.linear()
.domain([1, n - 1])
.rangeRound([0, width], .1);*/
var x = d3.scale.ordinal()
.domain(data.map(function(d) {
return d['name'];
}))
.rangeRoundBands([0, width], .5);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
/*.tickFormat(d3.format("d"))
.ticks(30)*/
;
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickFormat(d3.format("d"));
var svg = d3.select("#chart-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 layers = d3.layout.stack()
(status.map(function(c) {
return data.map(function(d) {
return {
x: d.name,
y: d[c],
};
});
}));
y.domain([
0, d3.max(layers[layers.length - 1], function(d) {
return d.y0 + d.y;
})
]);
// gridlines in y axis function
function make_y_gridlines() {
return d3.svg.axis().scale(y)
.orient("left").ticks(5);
}
// add the Y gridlines
svg.append("g")
.attr("class", "gridline")
.call(make_y_gridlines()
.tickSize(-width)
.tickFormat("")
);
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(6," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "translate(364,0)")
.attr("y", "3em")
.style("text-anchor", "middle")
.text("Days");
svg.append("g")
.attr("class", "axis axis--y")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("x", "-5em")
.attr("y", "-2.5em")
.style("text-anchor", "end")
.text("Number of calls sent");
function type(d) {
// d.date = parseDate(d.date);
d.date;
status.forEach(function(c) {
d[c] = +d[c];
});
return d;
}
var tooltip = d3.select("#chart-bar").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) {
return z(i);
});
layer.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html("<span>" + d.y + " calls" + "</span>")
.style("left", (d3.event.pageX - 25) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("x", function(d) {
return x(d.x) + x.rangeBand()/2;
})
.attr("y", function(d) {
return height;
})
.attr("width", 12)
.attr("height", 0)
.transition().duration(1500)
.attr("y", function(d) {
return y(d.y + d.y0);
})
.attr("height", function(d) {
return y(d.y0) - y(d.y + d.y0);
});
}
drawBarGraph(barDataset);
$('.count').each(function() {
$(this).prop('Counter', 0).animate({
Counter: $(this).text()
}, {
duration: 1500,
easing: 'swing',
step: function(now) {
$(this).text(Math.ceil(now));
}
});
});
#import url("https://fonts.googleapis.com/css?family=Overpass");
* {
box-sizing: border-box;
font: normal 14px/1.5 "Overpass", sans-serif;
}
body {
background: #76daff;
}
.chart-wrapper {
background: #333B66;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
clear: both;
padding: 20px 0 10px;
}
text {
font-size: 12px;
fill: #A7B2EB;
}
.axis path,
.axis line,
.gridline line {
fill: none;
stroke: #fff;
opacity: 0.1;
shape-rendering: crispEdges;
}
.line {
stroke: #17EAD9;
stroke-width: 3px;
fill: none;
}
path.domain {
fill: none;
opacity: 0.1;
}
div.tooltip {
color: #4a4a4a;
position: absolute;
text-align: center;
padding: 3px 6px;
font-size: 12px;
background: #fff;
border-radius: 4px;
pointer-events: none;
}
.tick text {
font-size: 10px;
}
.vbroadcast-legend {
float: right;
margin-right: 40px;
margin-top: 16px;
}
.vbroadcast-legend li {
color: #fff;
font-size: 13px;
float: left;
list-style: none;
margin-left: 20px;
padding-left: 18px;
position: relative;
}
.vbroadcast-legend li:before {
content: "";
height: 12px;
left: 0;
position: absolute;
top: 3px;
width: 12px;
}
.vbroadcast-legend li.successful:before {
background: #50e3c2;
}
.vbroadcast-legend li.unsuccessful:before {
background: #ef5c6e;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart-bar" class="chart-wrapper"></div>
Hope this helps solve the issue.
If you have a list of 'aa' .. 'jj' and you set the domain of x to this list you most likely do not get tick marks like '0-15' and '15-30'.
Extract the x-domain values from the dataset or some other means of extracting the unique values. This is with the small dataset in the question.
var strn = ['aa', 'bb', 'cc', 'dd', 'ee', 'ff', 'gg', 'hh', 'ii', 'jj'];
// ...
//x.domain(strn);
x.domain(data.map(d=>d.DB));

Sortable bar chart with long x axis labels rotated

I need to adjust Mike Bostock's sortable bar chart (available here) for long X axis labels. I have rotated them as slightly vertical and the initial result is that they are well separated and under the X axis but when the sorting process begins, they fall back on the axis.
If anyone could help me set the labels in the right place, I would be very happy!
My JSFiddle is available here and the JavaScript code is as follows:
var margin = {
top: 20,
right: 20,
bottom: 60,
left: 40
},
width = 960 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 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 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 + ")");
data = [{
letter: "Alongname1",
frequency: 0.08167
},
{
letter: "Alongname2",
frequency: 0.01492
},
{
letter: "Alongname3",
frequency: 0.0278
},
{
letter: "Alongname4",
frequency: 0.04253
},
{
letter: "Alongname5",
frequency: 0.12702
},
{
letter: "Alongname6",
frequency: 0.02288
},
{
letter: "Alongname7",
frequency: 0.02022
},
{
letter: "Alongname8",
frequency: 0.06094
},
{
letter: "Alongname9",
frequency: 0.06973
},
{
letter: "Alongname10",
frequency: 0.00153
},
{
letter: "Alongname11",
frequency: 0.00747
},
{
letter: "Alongname12",
frequency: 0.04025
},
{
letter: "Alongname13",
frequency: 0.02517
},
{
letter: "Alongname14",
frequency: 0.06749
},
{
letter: "Alongname15",
frequency: 0.07507
},
{
letter: "Alongname16",
frequency: 0.01929
},
{
letter: "Alongname17",
frequency: 0.00098
},
{
letter: "Alongname18",
frequency: 0.05987
}
];
data.forEach(function(d) {
d.frequency = +d.frequency;
});
x.domain(data.map(function(d) {
return d.letter;
}));
y.domain([0, d3.max(data, function(d) {
return d.frequency;
})]);
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", ".35em")
.attr("transform", "rotate(-65)");
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("Frequency");
svg.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);
});
var sortTimeout = setTimeout(function() {
d3.select("input").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(sortTimeout);
// Copy-on-write since tweens are evaluated after a delay.
var x0 = x.domain(data.sort(this.checked ?
function(a, b) {
return b.frequency - a.frequency;
} :
function(a, b) {
return d3.ascending(a.letter, b.letter);
})
.map(function(d) {
return d.letter;
}))
.copy();
svg.selectAll(".bar")
.sort(function(a, b) {
return x0(a.letter) - x0(b.letter);
});
var transition = svg.transition().duration(750),
delay = function(d, i) {
return i * 50;
};
transition.selectAll(".bar")
.delay(delay)
.attr("x", function(d) {
return x0(d.letter);
});
transition.select(".x.axis")
.call(xAxis)
.selectAll("g")
.delay(delay);
}
That behaviour is actually expected: when you call the axis again, the axis generator resets the dx and dy attributes.
You can apply them again after the second call, just as you did in the first one, but you'll notice that the texts will quickly flicker before going to their new positions.
So, an easy alternative, that avoids the flickering, is setting the labels' positions using the rotate itself. For instance (hardcoded values):
.attr("transform", "rotate(-65 12 32)");
Here is the code with that change:
var margin = {
top: 20,
right: 20,
bottom: 60,
left: 40
},
width = 960 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 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 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 + ")");
data = [{
letter: "Alongname1",
frequency: 0.08167
},
{
letter: "Alongname2",
frequency: 0.01492
},
{
letter: "Alongname3",
frequency: 0.0278
},
{
letter: "Alongname4",
frequency: 0.04253
},
{
letter: "Alongname5",
frequency: 0.12702
},
{
letter: "Alongname6",
frequency: 0.02288
},
{
letter: "Alongname7",
frequency: 0.02022
},
{
letter: "Alongname8",
frequency: 0.06094
},
{
letter: "Alongname9",
frequency: 0.06973
},
{
letter: "Alongname10",
frequency: 0.00153
},
{
letter: "Alongname11",
frequency: 0.00747
},
{
letter: "Alongname12",
frequency: 0.04025
},
{
letter: "Alongname13",
frequency: 0.02517
},
{
letter: "Alongname14",
frequency: 0.06749
},
{
letter: "Alongname15",
frequency: 0.07507
},
{
letter: "Alongname16",
frequency: 0.01929
},
{
letter: "Alongname17",
frequency: 0.00098
},
{
letter: "Alongname18",
frequency: 0.05987
}
];
data.forEach(function(d) {
d.frequency = +d.frequency;
});
x.domain(data.map(function(d) {
return d.letter;
}));
y.domain([0, d3.max(data, function(d) {
return d.frequency;
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("transform", "rotate(-65 12 32)");
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("Frequency");
svg.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);
});
var sortTimeout = setTimeout(function() {
d3.select("input").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(sortTimeout);
// Copy-on-write since tweens are evaluated after a delay.
var x0 = x.domain(data.sort(this.checked ?
function(a, b) {
return b.frequency - a.frequency;
} :
function(a, b) {
return d3.ascending(a.letter, b.letter);
})
.map(function(d) {
return d.letter;
}))
.copy();
svg.selectAll(".bar")
.sort(function(a, b) {
return x0(a.letter) - x0(b.letter);
});
var transition = svg.transition().duration(750),
delay = function(d, i) {
return i * 50;
};
transition.selectAll(".bar")
.delay(delay)
.attr("x", function(d) {
return x0(d.letter);
});
transition.select(".x.axis")
.call(xAxis)
.selectAll("g")
.delay(delay);
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: relative;
width: 960px;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
fill-opacity: .9;
}
.x.axis path {
display: none;
}
label {
position: absolute;
top: 10px;
right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<label><input type="checkbox"> Sort values</label>

d3 error displaying datetime on x-axis line chart

I am implementing a multi-line series chart using d3.js and I am getting an error pointing to my x-axis when trying to plot my dateTime from the data coming in. "Error: attribute d: Expected number, "MNaN,376.88020650…"."
Here is my function
var data = [{
"Brand": "Toyota",
"Count": 1800,
"Time": "2017-04-02 16"},
{
"Brand": "Toyota",
"Count": 1172,
"Time": "2017-04-02 17"},
{
"Brand": "Toyota",
"Count": 2000,
"Time": "2017-04-02 18"},
{
"Brand": "Honda",
"Count": 8765,
"Time": "2017-04-02 16"},
{
"Brand": "Honda",
"Count": 3445,
"Time": "2017-04-02 17"},
{
"Brand": "Honda",
"Count": 1232,
"Time": "2017-04-02 18"}
]
var dataGroup = d3.nest() //d3 method that groups data by Brand
.key(function(d) {return d.Brand;})
.entries(data);
console.log(JSON.stringify(dataGroup));
//var color = d3.scale.category10();
var vis = d3.select("#visualisation"),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 50,
right: 20,
bottom: 50,
left: 50
},
xScale = d3.scaleLinear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(data, function(d) { //set up x-axis based on data
return d.Time;
}), d3.max(data, function(d) {
return d.Time;
})]),
yScale = d3.scaleLinear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(data, function(d) { //set up y-axis based on data
return d.Count;
}), d3.max(data, function(d) {
return d.Count;
})]),
xAxis = d3.axisBottom()
.scale(xScale),
yAxis = d3.axisLeft()
.scale(yScale)
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineGen = d3.line()
.x(function(d) {
return xScale(d.Time);
})
.y(function(d) {
return yScale(d.Count);
})
.curve(d3.curveBasis);
dataGroup.forEach(function(d,i) { //iterate over the dataGroup and create line graph for each brand
vis.append('svg:path')
.attr('d', lineGen(d.values))
.attr('stroke', function(d,j) {
return "hsl(" + Math.random() * 360 + ",100%,50%)"; //random color for each brand line on graph
})
.attr('stroke-width', 2)
.attr('id', 'line_'+d.key)
.attr('fill', 'none');
lSpace = WIDTH/dataGroup.length; //define the legend space based on number of brands
vis.append("text")
.attr("x", (lSpace/2)+i*lSpace)
.attr("y", HEIGHT)
.style("fill", "black")
.attr("class","legend")
.on('click',function(){
var active = d.active ? false : true;
var opacity = active ? 0 : 1;
d3.select("#line_" + d.key).style("opacity", opacity);
d.active = active;
})
.text(d.key);
});
My dates are in yyyy-mm-dd HH format and what I am trying to accomplish is this for example:
"Time": "2017-04-02 16" converted to 'April 02' on the x axis and have the hour (HH) just displayed as a tool tip...etc
Here is a jsfiddle link https://jsfiddle.net/rsov2s2s/
Any help is appreciated.
In your data objects, Time is only a string. Thus, you`ll have to parse it into an actual date:
data.forEach(function(d){
d.Time = d3.timeParse("%Y-%m-%d %H")(d.Time)
});
In this function, d3.timeParse uses "%Y-%m-%d %H" as a specifier, which matches the structure of your strings.
After that, don't forget to change the xScale from scaleLinear to scaleTime.
Here is your code with those changes only:
var data = [{
"Brand": "Toyota",
"Count": 1800,
"Time": "2017-04-02 16"
}, {
"Brand": "Toyota",
"Count": 1172,
"Time": "2017-04-02 17"
}, {
"Brand": "Toyota",
"Count": 2000,
"Time": "2017-04-02 18"
}, {
"Brand": "Honda",
"Count": 8765,
"Time": "2017-04-02 16"
}, {
"Brand": "Honda",
"Count": 3445,
"Time": "2017-04-02 17"
}, {
"Brand": "Honda",
"Count": 1232,
"Time": "2017-04-02 18"
}];
data.forEach(function(d) {
d.Time = d3.timeParse("%Y-%m-%d %H")(d.Time)
});
var dataGroup = d3.nest() //d3 method that groups data by Brand
.key(function(d) {
return d.Brand;
})
.entries(data);
//var color = d3.scale.category10();
var vis = d3.select("#visualisation"),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 50,
right: 20,
bottom: 50,
left: 50
},
xScale = d3.scaleTime().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(data, function(d) { //set up x-axis based on data
return d.Time;
}), d3.max(data, function(d) {
return d.Time;
})]),
yScale = d3.scaleLinear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(data, function(d) { //set up y-axis based on data
return d.Count;
}), d3.max(data, function(d) {
return d.Count;
})]),
xAxis = d3.axisBottom()
.scale(xScale),
yAxis = d3.axisLeft()
.scale(yScale)
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineGen = d3.line()
.x(function(d) {
return xScale(d.Time);
})
.y(function(d) {
return yScale(d.Count);
})
.curve(d3.curveBasis);
dataGroup.forEach(function(d, i) { //iterate over the dataGroup and create line graph for each brand
vis.append('svg:path')
.attr('d', lineGen(d.values))
.attr('stroke', function(d, j) {
return "hsl(" + Math.random() * 360 + ",100%,50%)"; //random color for each brand line on graph
})
.attr('stroke-width', 2)
.attr('id', 'line_' + d.key)
.attr('fill', 'none');
lSpace = WIDTH / dataGroup.length; //define the legend space based on number of brands
vis.append("text")
.attr("x", (lSpace / 2) + i * lSpace)
.attr("y", HEIGHT)
.style("fill", "black")
.attr("class", "legend")
.on('click', function() {
var active = d.active ? false : true;
var opacity = active ? 0 : 1;
d3.select("#line_" + d.key).style("opacity", opacity);
d.active = active;
})
.text(d.key);
});
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
.legend {
font-size: 14px;
font-weight: bold;
cursor: pointer;
<title>D3 Test</title>
<script src="https://d3js.org/d3.v4.js"></script>
<body>
<svg id="visualisation" width="1000" height="600"></svg>
<script src="InitChart.js"></script>
</body>

d3 area between two line graphs [duplicate]

This question already has an answer here:
Using d3 to shade area between two lines
(1 answer)
Closed 6 years ago.
I want to fill the lines between two area graphs defined below. I am hitting a bit of a wall -- the issue I seem to have that each path I created does NOT have the other value to compare with, and my efforts to find a work around seem to have hit a bit of a wall.
Any tips?
jQuery(document).ready(function ($) {
var margin = {top: 20, right: 30, bottom: 40, left: 24},
width = 430 - margin.left - margin.right,
height = 225 - margin.top - margin.bottom,
dotRadius = function() { return 3 };
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')
.tickFormat(d3.time.format('%b'));
var yAxis = d3.svg.axis()
.scale(y)
.orient('left');
// This is a function that determines the colours of the lines drawn, up to 10.
var color = d3.scale.category10();
// This is used to format the time for our data.
var formatTime = d3.time.format("%Y-%m-%d");
var line = d3.svg.line()
.x(function(d) { return x(d.Period); })
.y(function(d) { return y(d.Value); })
var areaBetweenGraphs = d3.svg.area()
.x(function(d) {
console.log('ABG x is: ', d);
return x(formatTime.parse(d.Time));
})
.y0(function(d) {
console.log('ABG y0 is: ', d);
return y(d.Quantity);
})
.y1(function(d) {
console.log('ABG y1 is: ', d);
return y(d.Amount);
});
var svg = d3.select("#pipeline-chart-render")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
// This separates the data into the lines we want, although the data is stored
// In the same original object.
color.domain(d3.keys(data[0].values[0]).filter(function(key) {
if (key === 'Amount'
|| key === 'Quantity') {
return key
}
}));
// This returns the data into two separate objects which can be graphed.
// In this case, Amount and Quantity.
var datasets = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
Period: formatTime.parse(d.values[0].Time),
Value: +d.values[0][name]};
})
};
});
console.log('datasets is: ', datasets);
// set the minYDomainValue to zero instead of letting it be a lingering magic number.
var minDomainValue = 0
var minDate = d3.min(datasets, function(d0){
return d3.min(d0.values, function(d1){
return d1.Period;
})
}),
maxDate = d3.max(datasets, function(d0){
return d3.max(d0.values, function(d1){
return d1.Period;
})
});
x.domain([minDate, maxDate]);
y.domain([
minDomainValue,
d3.max(datasets, function(c) { return d3.max(c.values, function(v) { return v.Value; }); })
])
// Append the x-axis class and move axis around.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
// Append the y-axis class.
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append('g')
var pipeline = svg.selectAll('.pipeline')
.data(datasets);
pipeline.enter()
.append('g')
.attr('class', 'pipeline');
pipeline.append('path')
.attr('class', 'line')
.attr('id', function(d, i) {
return 'pipeline-'+(i+1);
})
.attr('d', function(d) { console.log('line d is: ', d); return line(d.values); })
.attr("data-legend",function(d) { return d.name})
.style("stroke", function(d) { return color(d.name); })
pipeline.exit().remove()
// Rendering the points on the graph.
var points = svg.selectAll('.pipelinePoint')
.data(datasets);
points
.enter()
.append('g')
.attr('class', 'pipelinePoint');
points.selectAll('.point')
.data(function(d) {
return d.values;
})
.enter()
.append('circle')
.attr('circleId', function(d, i) {
return 'circleId-'+i;
})
.attr('cx', function(d) {
return x(d.Period);
})
.attr('cy', function(d) {
return y(d.Value);
})
.attr('r', function(d) {
return dotRadius()
});
});
var data = [
{
key: 1,
values: [
{
Amount: 33,
Quantity: 22,
Time: '2015-01-01'
}
]
},
{
key: 2,
values: [
{
Amount: 52,
Quantity: 20,
Time: '2015-02-01'
}
]
},
{
key: 3,
values: [
{
Amount: 63,
Quantity: 30,
Time: '2015-03-01'
}
]
},
{
key: 4,
values: [
{
Amount: 92,
Quantity: 60,
Time: '2015-04-01'
}
]
},
{
key: 5,
values: [
{
Amount: 50,
Quantity: 29,
Time: '2015-05-01'
}
]
},
{
key: 6,
values: [
{
Amount: 53,
Quantity: 25,
Time: '2015-06-01'
}
]
},
{
key: 7,
values: [
{
Amount: 46,
Quantity: 12,
Time: '2015-07-01'
}
]
},
{
key: 8,
values: [
{
Amount: 52,
Quantity: 15,
Time: '2015-08-01'
}
]
},
{
key: 9,
values: [
{
Amount: 55,
Quantity: 20,
Time: '2015-09-01'
}
]
},
{
key: 10,
values: [
{
Amount: 35,
Quantity: 17,
Time: '2015-10-01'
}
]
},
{
key: 11,
values: [
{
Amount: 80,
Quantity: 45,
Time: '2015-11-01'
}
]
},
{
key: 12,
values: [
{
Amount: 64,
Quantity: 24,
Time: '2015-12-01'
}
]
}
]
CSS if you want it to be a less ugly render:
/* Line Chart CSS */
.axis path,
.axis line {
fill: none;
stroke: #000;
stroke-width: 3px;
shape-rendering: crispEdges;
}
#pipeline-1,
#pipeline-2 {
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
transition-delay: 250ms
-moz-transition-delay: 250ms;
-webkit-transition-delay: 250ms;
}
.x.axis path {
/* Uncomment below if I want to remove x-axis line */
/* display: none;*/
}
.line.hover path {
stroke-width: 6px;
}
#pipeline-chart-render {
padding-left: -50px;
}
.area {
fill: steelblue;
}
This ended up working.
// The following is for defining the area BETWEEN graphs.
var areaAboveQuantity = d3.svg.area()
.x(line.x())
.y0(line.y())
.y1(0);
var areaBelowQuantity = d3.svg.area()
.x(line.x())
.y0(line.y())
.y1(height);
var areaAboveAmount = d3.svg.area()
.x(line.x())
.y0(line.y())
.y1(0);
var areaBelowAmount = d3.svg.area()
.x(line.x())
.y0(line.y())
.y1(height);
var defs = svg.append('defs');
defs.append('clipPath')
.attr('id', 'clip-quantity')
.append('path')
.datum(datasets)
.attr('d', function(d) {
return areaAboveQuantity(d[1].values);
});
defs.append('clipPath')
.attr('id', 'clip-amount')
.append('path')
.datum(datasets)
.attr('d', function(d) {
return areaAboveAmount(d[0].values);
});
svg.append('path')
.datum(datasets)
.attr('class', 'area')
.attr('d', function(d) {
return areaBelowQuantity(d[1].values)
});
// Quantity IS ABOVE Amount
svg.append('path')
.datum(datasets)
.attr('d', function(d) {
areaBelowQuantity(d[1].values);
})
.attr('clip-path', 'url(#clip-amount)')
.style('fill', 'steelblue')
.style('opacity', '0.2');
// Amount IS ABOVE Quanity
svg.append('path')
.datum(datasets)
.attr('d', function(d) {
return areaBelowAmount(d[0].values);
})
.attr('clip-path', 'url(#clip-quantity)')
.style('fill', 'steelblue')
.style('opacity', '0.2');

Categories