Y and Height Values for Stacked Bar Chart in D3 - javascript

I'm trying to render a stacked bar chart from a multidimensional array that is grouped together by stack, and I can't figure out how to configure the y and height values of each rectangle. The tutorial I've been going off is here, but their data structure varies greatly from mine. I believe the solution is in how the y0 and y1 values are determined, but being a novice in D3 I'm unable to discern how it's being computed in the tutorial.
Here's what I have so far (the returned data from the data and legendLabels variables is at the top:
data = [["Privés dans les trois dimensions","30.2"],["Privés dans une dimension additionelle","24.4"],["Privés seulement dans la dimension spécifiée","8.32"],["Privés dans les trois dimensions","30.2"],["Privés dans une dimension additionelle","26.1"],["Privés seulement dans la dimension spécifiée","3.75"],["Privés dans les trois dimensions","30.2"],["Privés dans une dimension additionelle","33.1"],["Privés seulement dans la dimension spécifiée","10.4"]]
legendLabels = ["Nutrition","Santé","Eau"];
var $chart = $(chart),
data = $chart.data("chartDataTest"),
legendLabels = $chart.data("chartLabels"),
groupedData = [];
$.each(legendLabels, function(i){
var labelLength = legendLabels.length,
dataLength = data.length;
var sliceBeginning = i * labelLength,
sliceEnd = sliceBeginning + labelLength;
dataRange = data.slice(sliceBeginning, sliceEnd);
groupedData.push(dataRange);
});
var yValues = [];
$.each(groupedData, function(i, dataGroup){
var subGroupY = 0;
$.each(dataGroup, function(ii, dataSubGroup){
subGroupY += +dataSubGroup[1];
});
yValues.push(subGroupY);
});
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select(chart).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "parent-group")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(legendLabels.map(function(d) { return d; }));
x0.domain(groupedData.map(function(d) { return d; }));
y.domain([0, d3.max(yValues, function(d) { return d; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var group = svg
.selectAll(".group")
.data(groupedData)
.enter()
.append("g")
.attr("class", "g")
.attr("transform", function(d) {
return "translate(" + x0(d) + ",0)";
});
var yPosition = 0;
group
.selectAll(".group")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d, i) {
return y(d[1]);
})
.attr("height", function(d) {
return y(d[1]);
});
Here's what my chart looks like so far:

Per #CoolBlue's suggestion, I rerefactored this to use d3's stack function. I based my new approach on this tutorial. Here's the updated code:
var $chart = $(chart),
data = $chart.data("chartDataTest"),
chartStacks = $chart.data("chartLabels"),
groupedData = [],
colors = [];
var width = 900,
height = 500,
margin = { top: 10, right: 50, bottom: 30, left: 50},
x = d3.scale.ordinal().rangeRoundBands([0, width - margin.left - margin.right]),
x0 = d3.scale.ordinal().rangeRoundBands([0, width - margin.left - margin.right], 0.1),
y = d3.scale.linear().range([0, height - margin.top - margin.bottom]);
y0 = d3.scale.linear().range([height - margin.top - margin.bottom, 0]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom"),
yAxis = d3.svg.axis()
.scale(y0)
.orient("left")
.tickFormat(d3.format(".2s"));
$.each(chartStacks, function(i){
var labelLength = chartStacks.length,
dataLength = data.length;
var sliceBeginning = i,
dataRange = data.slice(sliceBeginning);
colorGroup = [];
$.each(dataRange, function(ii, colorData){
if ( ii % labelLength == 0) {
colorGroup.push(colorData[1]);
}
});
var remappedValues = colorGroup.map(function(dat, i) {
return {
x: i,
y: +dat
}
});
var remappedColors = dataRange.map(function(dat, i) {
return dat[0];
});
colors.push(remappedColors[0]);
groupedData.push(remappedValues);
});
var stacked = d3.layout.stack()(groupedData);
x0.domain(chartStacks.map(function(d) { return d; }));
x.domain(stacked[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(stacked[stacked.length - 1], function(d) { return d.y0 + d.y; })]);
y0.domain([0, d3.max(data, function(d) { return 90; })]);
var svg = d3.select(chart).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + ", " + 46 + ")")
.call(yAxis);
var svgContent = svg
.append("g")
.attr("class", "parent-group")
.attr("transform", "translate(" + margin.left + "," + height + ")");
var valGroup = svgContent
.selectAll(".parent-group")
.data(stacked)
.enter()
.append("g")
.attr("class", "valgroup");
var rect = valGroup.selectAll("rect")
.data(function(d){return d;})
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand() - 15);

Related

d3.js scaleBand()'s ticks coming out of place

I am using scaleBand() for both x and y axes for a bar chart. For some reason, the height of the bars are in between the ticks of the y axis. I would appreciate any help. Here is my code:
var margin_ = { top: 20, right: 20, bottom: 30, left: 40 },
width_ = 960 - margin_.left - margin_.right,
height_ = 500 - margin_.top - margin_.bottom;
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 x = d3.scaleBand()
.range([0, width_])
.padding(0.2)
var y = d3.scaleBand()
.range([height_, 0]);
x.domain(satisfactScaleKeyValues);
y.domain(graphYvalues);
svg_.selectAll(".bar")
.data(datas)
.enter().append("rect")
.attr("class", "bar__")
.attr("x", function (d) { return x(d.variable); })
.attr("width", x.bandwidth())
.attr("y", function (d) { return y(d.satisLevel); })
.attr("height", function (d) { return height_ - y(d.satisLevel); });
// add the x Axis
svg_.append("g")
.attr("transform", "translate(0," + height_ + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg_.append("g")
.call(d3.axisLeft(y))
You should use d3.scalePoint, which would provide a better translation from an ordinal domain to linear points on a range:
let datas = [{variable: 1, satisLevel: "Neutral"}]
var margin_ = { top: 20, right: 50, bottom: 30, left: 75 },
width_ = 960 - margin_.left - margin_.right,
height_ = 500 - margin_.top - margin_.bottom;
var svg_ = d3.select("body").append("svg")
.attr("width", width_ + margin_.left + margin_.right)
.attr("height", height_ + margin_.top + margin_.bottom)
var g = svg_.append("g")
.attr("transform",
"translate(" + margin_.left + "," + margin_.top + ")");
var x = d3.scaleBand()
.range([0, width_])
.padding(0.2)
var y = d3.scalePoint()
.range([height_, 0])
.padding(0.2)
x.domain([1]);
y.domain(["Not satisfied", "Neutral", "Satisfied"]);
g.selectAll(".bar")
.data(datas)
.enter().append("rect")
.attr("class", "bar__")
.attr("x", function (d) { return x(d.variable); })
.attr("width", x.bandwidth())
.attr("y", function (d) { return y(d.satisLevel); })
.attr("height", function (d) { return height_ - y(d.satisLevel); });
// add the x Axis
g.append("g")
.attr("transform", "translate(0," + height_ + ")")
.call(d3.axisBottom(x));
// add the y Axis
g.append("g")
.call(d3.axisLeft(y))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
If you want the height of the lowest Satisfaction Level to be more than zero, you can add padding to the scalePoint, like in the example.

D3: <rect> attribute x: Expected length, "NaN". error

I have to implement a bar chart in D3, but my values on the x axis are of type Date, data type which the D3 library should accept, but it seems to give me an error like this: attribute x: Expected length, "NaN".
This is the code for my bar chart:
//this holds the data that will be drawn
var data = [ {"yy":12,"mm":01,ppm_value:90000}, {"yy":11,"mm":02,ppm_value:50000}];;
//formats the date
var format = d3.time.format("%Y-%m-%d");
//define margins, height and width
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
w = 1000 - margin.left - margin.right,
h = 500 - margin.top - margin.bottom;
/*var x = d3.time.scale()
//.domain([0, d3.max(data, function(d) { return d.date; })])
.range([0, w], 0.6);*/
var x = d3.time.scale()
.range([0, w]);
var y = d3.scale.linear()
//.domain([0, d3.max(data, function(d) { return d.ppm_value;})])
.range([h, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
//.tickFormat(d3.time.format("%Y/%m"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.scaleExtent([1, 1])
.x(x)
.on("zoom", zoomed);
//create the svg
var chart = d3.select("#testChart").append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
var rect = chart.append("rect")
.attr("width", w)
.attr("height", h)
.style("fill", "none")
.style("pointer-events", "all");
//loops through data
data.forEach(function (d) {
//coerce to number
d.ppm_value = +d.ppm_value;
d.yy = +d.yy;
d.mm = +d.mm;
d.date = new Date("20" + d.yy + "/" +d.mm);
var dateTick = format(d.date);
d.date = dateTick;
console.log(d.ppm_value);
//console.log(dateTick);
//console.log(d.date);
});
//var dates = data.map(function(d){ return new Date("2016/01/03"); });
//console.log(formDate);
//map values onto x axis
x.domain([d3.min(data, function(d) { return d.date; }), d3.max(data, function(d) { return d.date; })])
// x.domain([0, d3.max(function(d) { return d.date; })]);
//map values onto y axis
y.domain([0, d3.max(data, function(d) { return d.ppm_value; })]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
var bars = chart.append("g")
.attr("class", "chartobjects");
bars.selectAll(".rect")
.data(data)
.enter().append("rect")
.attr("class", "rectBar")
.on("click",hello)
.attr('x', function(d) {
console.log(d.date);
return x(new Date(d.date));
})
.attr("y", function(d) {
return y(d.ppm_value);
console.log(d.ppm_value);
})
.attr("height", function(d) {
return h - y(d.ppm_value);
})
.attr("width", 15)
.attr("fill", function(d) {
return d.ppm_value > 6 ? "blue" : "red"
});
function hello() {
alert("Hello world!!")
}
function zoomed() {
console.log("Entered zoom function!!!");
var tx = Math.max(0, d3.event.translate[0])
//ty = Math.min(0, d3.event.translate[1]);
zoom.translate([tx]);
bars.attr("transform", "translate(" + [tx] + ")scale(" + d3.event.scale + ")");
chart.select(".x.axis")
.call(xAxis);
//chart.select(".y.axis")
// .call(yAxis);
}
I can not seem to get to the root of the problem. Am I doing something wrong ? What is the problem in your opinion ?
Thanks in advance!

Bar chart scale

I have this bar chart on D3.js... It works fine..
But I'm having problems with the scale... When a data series has a value much grater than the others, the <rect> does not fit into the scale.
Any idea how to solve this matter?
Here is the code:
var data = [
{"Anio":"1999","CONTRAVENCIONAL":"78484","PENAL":"0","FALTAS":"0","MULTAS":"0","OTROS":"0","TOTAL":"78484"},
{"Anio":"2000","CONTRAVENCIONAL":"92879","PENAL":"0","FALTAS":"0","MULTAS":"0","OTROS":"0","TOTAL":"92879"},
{"Anio":"2001","CONTRAVENCIONAL":"100018","PENAL":"0","FALTAS":"1818","MULTAS":"0","OTROS":"0","TOTAL":"101836"},
{"Anio":"2002","CONTRAVENCIONAL":"101380","PENAL":"0","FALTAS":"3692","MULTAS":"0","OTROS":"0","TOTAL":"105072 "},
{"Anio":"2003","CONTRAVENCIONAL":"86791","PENAL":"0","FALTAS":"7417","MULTAS":"0","OTROS":"0","TOTAL":"94208"},
{"Anio":"2004","CONTRAVENCIONAL":"47870","PENAL":"255","FALTAS":"1105","MULTAS":"1811","OTROS":"0","TOTAL":"51041"},
{"Anio":"2005","CONTRAVENCIONAL":"33013","PENAL":"348","FALTAS":"1473","MULTAS":"634","OTROS":"0","TOTAL":"35468"},
];
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 860 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
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");
var arr_data = [];
for (var i = 0; i < data.length; i++) {
var o = {'name':data[i].Anio,'value':data[i].TOTAL};
arr_data.push(o);
};
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom )
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(arr_data.map(function(d) { return d.name; }));
y.domain([0, d3.max(arr_data, function(d) { return d.value; })]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
var bar = chart.selectAll(".bar")
.data(arr_data)
.enter().append("g");
bar.append("rect")
.attr("class", "rect")
.attr("x", function(d) { return x(d.name); })
.attr("y", function(d) { return y(d.value) ; })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x.rangeBand())
.attr("fill","#632423")
.on('mouseover',function(d){
var a = d3.select(this)
.attr("fill","#733A39");
var a = d3.select("#tooltip")
.style("left","100px")
.style("top","20px")
.select("#value")
.text(d.value);
}).on('mouseout',function(d){
var a = d3.select(this)
.attr("fill","#632423"); //old color: #790018
});
bar.append("text")
.attr("class", "label")
.text(function(d) { return d.value; })
.attr("x", function(d) { return x(d.name)+4; })
.attr("y", function(d) { return y(d.value)+20 ; });
Your scale will actually handle series with larger values for you because you're dynamically setting it to go from 0 to the max value in your data:
y.domain([0, d3.max(arr_data, function(d) { return d.value; })]);
However, you're not converting your data to numbers from strings, so right now the scale is from [0, 94208] instead of [0, 105072]. This is because the character "9" is greater than "1". You can fix this by converting the values to numbers when you construct your arr_data, like this:
var o = {'name':data[i].Anio,'value':+data[i].TOTAL}; // <---- notice the '+'
This produces a better looking graph:

Not able to plot rectangles using onclick function on a stack of each bar in stacked bar chart in d3

I am creating a stacked bar chart where stacks of each bar represents the status -"open","wip" respectively.what my requirement is that,triggering click event on each stacks of bar,3 rectangle should appear which represents "sev-high","sev-low","sev-medium" with respective count ...it means clicking on each stacks which represents "status",the total count for that status will get splited up into 3 bars showing "sev-high","sev-low","sev-medium" for that particular status..but here i am not able to plot the rectangle after clicking on stacks...please go through my code and suggest me ...
here is my code...
var data=[{"comp_catgry":"A","age":"0-5","status":"open","sev":"high","cnt":"40"}
,{"comp_catgry":"A","age":"0-5","status":"open","sev":"low","cnt":"10"}
,{"comp_catgry":"A","age":"0-5","status":"open","sev":"medium","cnt":"20"}
,{"comp_catgry":"A","age":"0-5","status":"wip","sev":"high","cnt":"40"}
,{"comp_catgry":"A","age":"0-5","status":"wip","sev":"low","cnt":"40"}
,{"comp_catgry":"A","age":"0-5","status":"wip","sev":"medium","cnt":"20"}
,{"comp_catgry":"A","age":"6-10","status":"open","sev":"high","cnt":"40"}
,{"comp_catgry":"A","age":"6-10","status":"open","sev":"low","cnt":"40"}
,{"comp_catgry":"A","age":"6-10","status":"open","sev":"medium","cnt":"40"}
,{"comp_catgry":"A","age":"6-10","status":"wip","sev":"high","cnt":"30"}
,{"comp_catgry":"A","age":"6-10","status":"wip","sev":"low","cnt":"40"}
,{"comp_catgry":"A","age":"6-10","status":"wip","sev":"medium","cnt":"10"}
,{"comp_catgry":"B","age":"0-5","status":"open","sev":"high","cnt":"40"}
,{"comp_catgry":"B","age":"0-5","status":"open","sev":"low","cnt":"50"}
,{"comp_catgry":"B","age":"0-5","status":"open","sev":"medium","cnt":"40"}
,{"comp_catgry":"B","age":"0-5","status":"wip","sev":"high","cnt":"40"}
,{"comp_catgry":"B","age":"0-5","status":"wip","sev":"low","cnt":"40"}
,{"comp_catgry":"B","age":"0-5","status":"wip","sev":"medium","cnt":"30"}
,{"comp_catgry":"B","age":"6-10","status":"open","sev":"high","cnt":"40"}
,{"comp_catgry":"B","age":"6-10","status":"open","sev":"low","cnt":"40"}
,{"comp_catgry":"B","age":"6-10","status":"open","sev":"medium","cnt":"40"}
,{"comp_catgry":"B","age":"6-10","status":"wip","sev":"high","cnt":"20"}
,{"comp_catgry":"B","age":"6-10","status":"wip","sev":"low","cnt":"40"}
,{"comp_catgry":"B","age":"6-10","status":"wip","sev":"medium","cnt":"30"}
]
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 760 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y0 = d3.scale.ordinal()
.rangeRoundBands([height, 0], .2);
var y1 = d3.scale.linear();
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
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 nestedData = d3.nest()
.key(function(d) {return d.comp_catgry;})
.key(function(d) {return d.age;})
.key(function(d) {return d.status;})
.entries(data);
console.log(nestedData);
var maxTotal = 0;
nestedData.forEach(function(catGroup) {
catGroup.ctgry = catGroup.key;
catGroup.values.forEach(function(ageGroup){
ageGroup.age = ageGroup.key;
ageGroup.bars=[];
var total1=0;
ageGroup.values.forEach(function(stsGroup){
stsGroup.sts=stsGroup.key;
var total = 0;
stsGroup.bars = [];
stsGroup.values.forEach(function(d){
stsGroup.bars.push(
{ctgry:catGroup.ctgry,
age:ageGroup.age,
status:d.status,
// type: "open",
sev:d.sev,
cnt1:d.cnt,
z0: total,
z1: (total = total + (+d.cnt) )
}
);
})
ageGroup.bars.push({
ctgry:catGroup.ctgry,
age:ageGroup.age,
status:stsGroup.key,
y0:total1,
y1:(total1 = total1 + total)
}
);
maxTotal = Math.max(maxTotal, total1);
});
});
});
x.domain( nestedData[0].values.map(function(d){return d.age;}) );
y0.domain(nestedData.map(function(d) { return d.key; }));
y1.domain([0, maxTotal]).range([y0.rangeBand(), 0]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var dateGroups = svg.selectAll("dateGroups")
.data(nestedData)
.enter()
.append("g")
.attr("class", "dateGroups")
.attr("transform", function(d) { return "translate(60," + y0(d.key) + ")"; });
dateGroups.append("text")
.attr("class", "group-label")
.attr("x", -76)
.attr("y", function(d) { return y0(d.values[0].value / 4); })
.attr("dy", ".35em")
.text(function(d) { return "Complaint Category " + d.key; })
var ageGroups = dateGroups.selectAll("ageGroups")
.data(function(d,i){console.log(nestedData[i].values); return nestedData[i].values;})
.enter()
.append("g")
.attr("class", "ageGroups")
var bars = ageGroups.selectAll("rect")
.data( function(d) {console.log(d.bars); return d.bars;})
.enter().append("rect")
.attr("id",function(d,i){return "Cust_"+i ;})
.attr("y", function(d){
return y1(d.y1);} )
.attr("height", function(d){return Math.abs( y1(d.y1) - y1(d.y0) ); } )
.attr("height", function(d) { return y0.rangeBand() - (Math.abs( y1(d.y1) - y1(d.y0) )); })
.attr("x", function(d,i){return x(d.age);})
.attr("width", x.rangeBand() )
.style("fill", function(d) { return color(d.status); })
/* .append("title")
.text(function(d) {
return ("Age Bucket-"+d.age + ", " +d.status +":" + d.count);
})*/
.on("click", function(d,i){
alert(1)
var bb = ageGroups.append("g").selectAll("rect").data( function(d) {console.log(d.values[i]); return d.values[i];})
.enter();
alert(2)
bb.append("rect")
.attr("id","rectId")
.attr("x",50)
.attr("Y",50)
.attr("height",function(d,i){ alert(3);console.log(d.bars[i].sev);return d.bars[i].sev;})
.attr("width",10)
.style("fill","red")
.style("visibility", "visible");
});

Y-axis transition results in changing side

I'm having a bizarre d3 issue wherein my y-axis transition results in the axis switching sides. Besides that, I am happy with how the transition looks. A gif that demonstrates the issue is available at https://i.imgflip.com/g4kdc.gif. I have followed a few examples including http://bl.ocks.org/mbostock/4323929, but can't seem to figure out the issue.
var dataset = [{
"year_decided": 1982,
"Total": 0
}, //some more data
{
"year_decided": "2000",
"Total": "310"
}]; // default dataset that we can access and override
var margin = {
top: 30,
right: 20,
bottom: 20,
left: 35
};
var w = $("#section").width() - margin.left - margin.right;
var h = $("#section").height() - margin.top - margin.bottom;
///create the default scales
var xScale = d3.scale.linear()
.domain([0,dataset.length])
.range([0,w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset,function(d){ return +d.Total }) ])
.range([h,0]);
// create the axes
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(6, 0)
.orient("bottom")
.tickFormat(function(d,i){
return d + 1982;
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.tickSize(w);
//define the svg and add it to the document
var svg = d3.select("#section").append("svg")
.attr("width",w + margin.left + margin.right)
.attr("height",h + margin.top + margin.bottom)
.attr("id", "main-chart");
svg.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
//add an axis group and add the y axis
var gy = svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.call(customAxis)
var gx = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + h + ")")
.call(xAxis);
//create the line
var line = d3.svg.line()
.x(function(d, i){ return xScale(i) })
.y(function(d){ return yScale(+d.Total) })
.interpolate("linear");
svg.append('path')
.classed('data-line', true)
.attr('d', line(dataset))
.attr("transform", "translate(" + margin.left + ",0)");
//create the tooltip
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 4.5)
.attr("transform", "translate(" + margin.left + ",0)")
;
var tool_tip_year = focus.append("text")
.attr("x", 9)
.attr("dy", ".35em")
.attr("transform", "translate(" + margin.left + ",0)")
;
var tool_tip_total = focus.append("text")
.attr("x", 9)
.attr("dy", "1.8em")
.attr("transform", "translate(" + margin.left + ",0)")
;
svg.append("rect")
.attr("class", "overlay")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(" + margin.left + ",0)")
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var bisectIndex = d3.bisector(function(d, i) { return i; }).left;
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = Math.round(x0),
d = dataset[i];
focus.attr("transform", "translate(" + xScale(i) + "," + yScale(+d.Total) + ")");
tool_tip_year.text(1982 + i);
tool_tip_total.text(d3.format(",")(+d.Total));
}
function customAxis(g){
g.selectAll("text")
.attr("x",4)
.attr("dy",-4);
}
//update the graph following http://bl.ocks.org/d3noob/7030f35b72de721622b8
$("#submission").submit(function(){
//define url to request
var submission = "php/data.php?word=" + $("#submission-text").val();
//request json and save as dataset
d3.json(submission, function(error, json) {
if (error) return console.warn(error);
dataset = json;
//rescale the graphs
xScale = d3.scale.linear()
.domain([0,dataset.length])
.range([0,w]);
yScale = d3.scale.linear()
.domain([0, d3.max(dataset,function(d){ return +d.Total }) ])
.range([h,0]);
gy.transition()
.duration(2500)
.call(yAxis);
gy.call(customAxis);
svg.select(".data-line")
.transition()
.duration(2000)
.attr("d",line(dataset));
})
});

Categories