Below is the code for a line chat in D3. Currently it displays all the values on the line but what I want to show is only the first and last point with a "B" appended at the end. How do I fix this?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Unemployment by Ward Bar Chart</title>
<style type="text/css">
.axis text{
font-family: Arial;
font-size: 13px;
color: #333333;
text-anchor: end;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.textlabel{
font-family: Arial;
font-size:13px;
color: #333333;
text-anchor: middle;
}
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 20, right: 0, bottom: 60, left: 60},
width = 475;
height = 350;
padding = 100;
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("viewBox", "0 0 " + width + " " + height);
// Parse the date / time
var parseDate = d3.time.format("%m/%d/%y").parse;
var formatTax = d3.format(",.2f");
// Set the ranges
var x = d3.time.scale()
.range([0, width - margin.right - margin.left], .1);
var y = d3.scale.linear()
.range([height - margin.top - margin.bottom, 0]);
// Define the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(function(d) {return "$" + d + "B"});
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.Date); })
.y(function(d) { return y(d["Tax Collections"]); });
// Get the data
d3.csv("Yearly Tax Collections.csv", function(error, data) {
data.forEach(function(d) {
d.Date = parseDate(d.Date);
d["Tax Collections"] = formatTax(+d["Tax Collections"]/1000000000);
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.Date; }));
y.domain([0, d3.max(data, function(d) { return d["Tax Collections"]; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + (height - margin.bottom) + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
// Y-axis labels
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate ("+ (padding/4) + "," +(height/2)+") rotate(-90)")
.text("Tax Revenue")
.style("font-family", "Arial");
// X-axis labels
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/2) + "," +(height-(padding/4)) + ")")
.text("Fiscal Year")
.style("font-family", "Arial");
//source
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/4.5) + "," +(height/1) + ")")
.text("Source: DC OCFO")
.style("font-family", "Arial")
//title for the chart
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/3) + "," +(height/30) + ")")
.text("DC Total Tax Revenues by Fiscal Year")
.style("font-family", "Arial");
svg.append("text")
.attr("text-anchor", "left")
.style("font-size", "10x")
.style("color", "#333333")
.attr("transform", "translate("+ (width/20) + "," +(height/12) + ")")
.text("2000 to 2015")
.style("font-family", "Arial")
//line labels
svg.append('g')
.classed('labels-group', true)
.selectAll('text')
.data(data)
.enter()
.append('text')
.classed('label',true)
.attr({
'x':function(d,i) {
return x(d.Date);
},
'y':function(d,i) {
return y(d["Tax Collections"]);
}
})
.text(function(d,i){
return d["Tax Collections"];
})
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
});
</script>
</body>
Thank you so much in advance!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Unemployment by Ward Bar Chart</title>
<style type="text/css">
.axis text{
font-family: Arial;
font-size: 13px;
color: #333333;
text-anchor: end;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.textlabel{
font-family: Arial;
font-size:13px;
color: #333333;
text-anchor: middle;
}
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 20, right: 0, bottom: 60, left: 60},
width = 475;
height = 350;
padding = 100;
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("viewBox", "0 0 " + width + " " + height);
// Parse the date / time
var parseDate = d3.time.format("%m/%d/%y").parse;
var formatTax = d3.format(",.2f");
// Set the ranges
var x = d3.time.scale()
.range([0, width - margin.right - margin.left], .1);
var y = d3.scale.linear()
.range([height - margin.top - margin.bottom, 0]);
// Define the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(function(d) {return "$" + d + "B"});
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.Date); })
.y(function(d) { return y(d["Tax Collections"]); });
// Get the data
d3.csv("Yearly Tax Collections.csv", function(error, data) {
data.forEach(function(d) {
d.Date = parseDate(d.Date);
d["Tax Collections"] = formatTax(+d["Tax Collections"]/1000000000);
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.Date; }));
y.domain([0, d3.max(data, function(d) { return d["Tax Collections"]; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + (height - margin.bottom) + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
// Y-axis labels
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate ("+ (padding/4) + "," +(height/2)+") rotate(-90)")
.text("Tax Revenue")
.style("font-family", "Arial");
// X-axis labels
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/2) + "," +(height-(padding/4)) + ")")
.text("Fiscal Year")
.style("font-family", "Arial");
//source
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "13px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/4.5) + "," +(height/1) + ")")
.text("Source: DC OCFO")
.style("font-family", "Arial")
//title for the chart
svg.append("text")
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("color", "#333333")
.attr("transform", "translate("+ (width/3) + "," +(height/30) + ")")
.text("DC Total Tax Revenues by Fiscal Year")
.style("font-family", "Arial");
svg.append("text")
.attr("text-anchor", "left")
.style("font-size", "10x")
.style("color", "#333333")
.attr("transform", "translate("+ (width/20) + "," +(height/12) + ")")
.text("2000 to 2015")
.style("font-family", "Arial")
//line labels
svg.append('g')
.classed('labels-group', true)
.selectAll('text')
.data(data)
.enter()
.append('text')
.filter(function(d, i) { return i === 0 || i === (data.length - 1) })
.classed('label',true)
.attr({
'x':function(d,i) {
return x(d.Date);
},
'y':function(d,i) {
return y(d["Tax Collections"]);
}
})
.text(function(d,i){
return "$" + d["Tax Collections"] + "B";
})
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
});
</script>
</body>
Assumes that the data array is sorted by date.
Related
I have a mistake and I can not find it, thanks for your help.
My data is called consumer_complaints.csv:
date_received,product,sub_product,issue,sub_issue,consumer_complaint_narrative,company_public_response,company,state,zipcode,tags,consumer_consent_provided,submitted_via,date_sent_to_company,company_response_to_consumer,timely_response, consumer_disputed,complaint_id
08/30/2013,Mortgage,Other mortgage,Loan modification,collection,foreclosure,U.S. Bancorp,CA,95993,Referral,09/03/2013,Closed with explanation,Yes,Yes,511074
My code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#ff0000", "#00ff00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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("consumer_complaints.csv", function(error, data) {
if (error) throw error;
var nested_data = d3.nest()
.key(function(d) { return d.submitted_via; })
.entries(data);
var subVia = [];
nested_data.forEach(function(d,i){
var count = 0;
subVia[i] = d.key;
d.values.forEach(function(v){
if(v.consumer_disputed == "Yes")
count++
});
d.dispu = [{name: "Yes",value: count/d.values.length},{name: "No",value:
(d.values.length-count)/d.values.length}];
});
x0.domain(subVia.forEach(function(d,i){ return subVia[i]; }));
x1.domain(subVia).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(nested_data, function(d) { return d3.max(d.dispu, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Satisfaction");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "state")
.attr("transform", subVia.forEach(
function(d,i) {console.log(subVia[i]); return "translate(" + x0(subVia[i]) + ",0)"; }));
state.selectAll("rect")
.data(function(d) { return d.dispu; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.key); });
var legend = svg.selectAll(".legend")
.data(subVia.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#ff0000", "#00ff00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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("consumer_complaints.csv", function(error, data) {
if (error) throw error;
var nested_data = d3.nest()
.key(function(d) { return d.submitted_via; })
.entries(data);
var subVia = [];
nested_data.forEach(function(d,i){
var count = 0;
subVia[i] = d.key;
d.values.forEach(function(v){
if(v.consumer_disputed == "Yes")
count++
});
d.dispu = [{name: "Yes",value: count/d.values.length},{name: "No",value:
(d.values.length-count)/d.values.length}];
});
x0.domain(subVia.forEach(function(d,i){ return subVia[i]; }));
x1.domain(subVia).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(nested_data, function(d) { return d3.max(d.dispu, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Satisfaction");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "state")
.attr("transform", subVia.forEach(
function(d,i) {console.log(subVia[i]); return "translate(" + x0(subVia[i]) + ",0)"; }));
state.selectAll("rect")
.data(function(d) { return d.dispu; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.key); });
var legend = svg.selectAll(".legend")
.data(subVia.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
I am new to D3.js
I've gone through some tutorials and have straight up jumped into my first project. I was hoping to combine the following with slight tweaks according to my needs. Currently I am having two issues
Focus+Context via Brushing
and
X-Value Mouseover
The Mouseover is wrongly displayed. It renders to the left of the chart. Could be a very small issue but I cant seem to find it.
I cant seem to figure out a way to display the "Safe Value" text outside the chart right next to the line. EDIT 2 - I've figured this out
Any help would be much appreciated.
Here is the CSS
body {
font: 10px sans-serif;
}
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: steelBlue;
stroke-width: 1.5px;
/*clip-path: url(#clip);*/
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.overlay {
fill: none;
pointer-events: all;
}
.xy circle {
fill: steelblue;
stroke: black;
}
JS
var margin = {top: 10, right: 15, bottom: 100, left: 60},
margin2 = {top: 430, right: 15, bottom: 20, left: 60},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%SZ").parse,
bisectDate = d3.bisector(function(d) { return d.date; }).left,
formatValue = d3.format(",.2f"),
formatData = function(d) { return formatValue(d) + " %"; };
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(d3.time.months, 1).tickFormat(d3.time.format("%m/%y")),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom").ticks(d3.time.months, 1).tickFormat(d3.time.format("%m/%y")),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
var line2 = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x2(d.date); })
.y(function(d) { return y2(d.value); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("data.csv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
data.sort(function(a, b) {
return a.date - b.date;
});
x.domain(d3.extent(data.map(function(d) { return d.date; })));
y.domain([0, d3.max(data.map(function(d) { return d.value; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
focus.append("line")
.attr("x1",x(data[0].date))
.attr("y1",y(83))
.attr("x2",x(data[data.length - 1].date))
.attr("y2",y(83))
.attr("stroke","orangered");
svg.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(83) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "orangered")
.text(function(d) { return "Safe Value = 83" });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("x", 0)
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(-50,"+ height/2 + ") rotate(-90)")
.text("Dissolved Oxygen (%)");
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
var xy = svg.append("g")
.attr("class", "xy")
.style("display", "none");
xy.append("circle")
.attr("r", 4.5);
xy.append("text")
.attr("x", 9)
.attr("dy", ".35em");
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.on("mouseover", function() { xy.style("display", null); })
.on("mouseout", function() { xy.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
console.log(x0);
xy.attr("transform", "translate(" + x(d.date) + "," + y(d.value) + ")");
xy.select("text").text(formatData(d.value));
}
});
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".line").attr("d", line);
focus.select(".x.axis").call(xAxis);
}
Plunker Code
(Please refer to the code at Plunker, since I have updated a few things over there.) Thanks
Image1
Image2
For your problem #2, the code for the text is placing it out of the visible area. Just adjust your arguments to translate to something like the following:
.attr("transform", "translate(" + (width - 35) + ",30" + ")")
or something else that you prefer - note the minus on the x.
Following is the data file : myStData.csv
xindex,mylabel
40,23
41,13
42,12
43,21
44,40
45,50
Following is my code snippet, and currently, the label is shown at "start" (text-anchor is set to start). It is placed at the start value of my csv file. But, I want the label to be placed at the end value.
I tried replacing the start text anchor to be end, but it didn't work in my case. Any help in this is highly appreciated.
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body { font: 13px Helvetica;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
text-anchor: start;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 40, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
//var x = d3.time.scale().range([0, width]);
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(14);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.xindex); })
.y(function(d) { return y(d.mylabel); });
var chart1 = d3.select("body")
.append("svg")
.attr("width", width + margin.left + (margin.right * 2))
.attr("height", height + margin.top + (margin.bottom * 2))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.csv("myStData.csv", function(error, data) {
data.forEach(function(d) {
d.xindex = +d.xindex;
d.mylabel = +d.mylabel;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.xindex; }));
y.domain([0, d3.max(data, function(d) { return d.mylabel; })]);
chart1.append("path") // Add the valueline path.
.attr("class", "line")
.attr("d", valueline(data));
chart1.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart1.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[0].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");
// Add the text label for the Y axis
chart1.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Y-Axis Label");
// Add the text label for the x axis
chart1.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + (margin.bottom * 1.5)) + ")")
.style("text-anchor", "middle")
.text("X-Axis Label");
});
Finally, I got the solution. Simple, as it was!
So, to re-iterate, what I wanted to achieve was to move the location of the 'MyLabel' label to the position where the line ends. Here's how it needs to be done:
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[0].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");
This states that the y-axis position of the label needs to be at data[0] element's y value. We simply need to replace, data[0] by data[data.length-1] so that the y- value of the last data element is taken into consideration for positioning the label.
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[data.length-1].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");
Problem
Having trouble getting my chart in D3 to show up. Getting an Uncaught SyntaxError: Unexpected end of input with my scripts.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<script src="assets/js/scripts.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
</body>
</html>
scripts.js
$(function() {
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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("assets/data/data.csv", function(error, data) {
var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; });
data.forEach(function(d) {
d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Population");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(ageNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
style.css
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: blue;
}
.x.axis path {
display: none;
}
I found that I got the same error when pasting your code directly into JSFiddle. It went away when I properly closed the main function. For reference, here's your code in live snippet form with the extra closing braces:
var csvData = [
{"State":0, "Age":31, "Names":["Austin"]},
{"State":0, "Age":31, "Names":["Austin"]},
{"State":0, "Age":31, "Names":["Austin"]},
];
$(function() {
$("#placeholder").remove();
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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 = csvData;
var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; });
data.forEach(function(d) {
d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Population");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(ageNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: blue;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
On the d3.csv("csv...") call - try adding another }); to the end of it.
I tried your code out on JSFiddle, and that seemed to resolve the syntax error.
EDIT: My bad. Left in a hurry. Here's the fiddle:
http://jsfiddle.net/strsjpxa/
I later noticed it made more sense to close the function at the end.
I am using the D3 toolkit to create a stacked bar graph of some data. I want link the bars to a separate page with more detail about the underlying data for that bar. I can't figure out how to turn the bars into hyperlinks. The code below is based on a demo that I have been tinkering with. When I inspect the code in Google Chrome it looks correct but the bars aren't clickable. Tremendous thanks in advance for ideas and suggestions on this!
Source, attempting to add link to Google to each bar:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="d3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
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("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("./data.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
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("Population");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("xlink:href", function(d) { return "http://www.google.com"; })
.attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); });
state.append("a")
.attr("xlink:href", "http://www.google.com")
;
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
I'm not sure that you can add "a" html mark in SVG.
But you can add an event on each bar segment:
state.on('click',function(d){
... some great code ...
})