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");
Related
Recently, maybe after updating Java, I'm unable to load a scatter plot on Chrome, Firefox or Internet Explorer.
One month ago, everything loaded fine. I don't know what happened. I've updated Java to the last version and enabled ActiveX on Internet options, but nothing works for me.
I'll paste the html code. It loads the point info using a csv file saved in the same folder:
<!DOCTYPE html> <meta charset="utf-8"> <style>
body { font: 12px Arial;}
.axis path, .axis line { fill: none; stroke: grey; stroke-width: 1;
shape-rendering: crispEdges; }
</style> <body>
<script src="http://d3js.org/d3.v4.js"></script> <script>
// Set the dimensions of the canvas / graph var margin = {top: 30, right: 20, bottom: 50, left: 60}, width = 900 - margin.left - margin.right, height = 360 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.timeParse("%a %b %d %H:%M:%S %Z %Y "); // Set the ranges
var y = d3.scaleTime().range([height, 0]); var x = d3.scaleLinear().range([0, width]);
// Define the axes
var xAxis = d3.axisBottom().scale(x) .ticks(5);
var yAxis = d3.axisLeft().scale(y)
.ticks(5);
// 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("transform", "translate(" + margin.left + "," + margin.top + ")"); // Get the data
d3.csv("data.csv", function(error, data) { var max = data.length; console.log(max)
data.forEach(function(d, i) { d.dateParsed = parseDate(d.date); d.close = max - i;
}); // Scale the range of the data
y.domain(d3.extent(data, function(d) { return d.dateParsed; })); x.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the scatterplot svg.selectAll("dot") .data(data)
.enter().append("circle") .attr("r", 0.5)
.attr("fill","#2980B9")
.attr("cy", function(d) { return y(d.dateParsed); }) .attr("cx", function(d) { return x(d.close); });
svg.append("g") .attr("class", "x axis")
.attr("transform", "translate(0," + height + ")") .call(xAxis);
svg.append("text") .attr("class", "x label") .attr("text-anchor", "middle") .attr("x", width / 2) .attr("y", height + 40) .text("followers");
svg.append("g")
.attr("class", "y axis") .call(yAxis);
svg.append("text") .attr("class", "y label") .attr("text-anchor", "middle") .attr("x", -height / 2 ) .attr("y", -50)
.attr("transform", "rotate(-90)") .text("account creation date");
});
</script> </body>
It looks like main issue is code is not formatted properly.
Many comments get mixed with the code caused the syntax errors.
I try to format the code and try to fix those errors.
As we don't have your data.csv file so we are not able to load that data but code creates the chart now.
You can try to use this code on your side with your data.csv file. It will help you to load the chart properly.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font: 12px Arial;}
.axis path, .axis line { fill: none; stroke: grey; stroke-width: 1;
shape-rendering: crispEdges; }
</style>
</head>
<body>
<script src="http://d3js.org/d3.v4.js"></script> <script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 50, left: 60}, width = 900 - margin.left - margin.right, height = 360 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.timeParse("%a %b %d %H:%M:%S %Z %Y "); // Set the ranges
var y = d3.scaleTime().range([height, 0]); var x = d3.scaleLinear().range([0, width]);
// Define the axes
var xAxis = d3.axisBottom().scale(x) .ticks(5);
var yAxis = d3.axisLeft().scale(y)
.ticks(5);
// 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("transform", "translate(" + margin.left + "," + margin.top + ")"); // Get the data
d3.csv("data.csv", function(error, data) { var max = data.length;
console.log(max);
data.forEach(function(d, i) { d.dateParsed = parseDate(d.date); d.close = max - i;
});
// Scale the range of the data
y.domain(d3.extent(data, function(d) { return d.dateParsed; })); x.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the scatterplot
svg.selectAll("dot") .data(data)
.enter().append("circle") .attr("r", 0.5)
.attr("fill","#2980B9")
.attr("cy", function(d) { return y(d.dateParsed); }) .attr("cx", function(d) { return x(d.close); });
svg.append("g") .attr("class", "x axis")
.attr("transform", "translate(0," + height + ")") .call(xAxis);
svg.append("text") .attr("class", "x label") .attr("text-anchor", "middle") .attr("x", width / 2) .attr("y", height + 40) .text("followers");
svg.append("g")
.attr("class", "y axis") .call(yAxis);
svg.append("text") .attr("class", "y label") .attr("text-anchor", "middle") .attr("x", -height / 2 ) .attr("y", -50)
.attr("transform", "rotate(-90)") .text("account creation date");
});
</script>
</body>
</html>
I've created a line chart using this http://bl.ocks.org/d3noob/6eb506b129f585ce5c8a code example. I've managed to recreate it.
that code is
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse,
formatDate = d3.time.format("%d-%b"),
bisectDate = d3.bisector(function(d) { return d.date; }).left;
// Set the ranges
// var x = d3.time.scale().range([0, width]);
var x = d3.scale.ordinal().rangePoints([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.interpolate('basis')
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// 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("transform",
"translate(" + margin.left + "," + margin.top + ")");
var lineSvg = svg.append("g");
var focus = svg.append("g")
.style("display", "none");
// Get the data
var data = [
{
"date": "w1",
"close": 629.32
},
{
"date": "w2",
"close": 124.31
},
{
"date": "w3",
"close": 333.68
},
{
"date": "w4",
"close": 236.23
}
]
// data.forEach(function(d) {
// // d.date = parseDate(d.date);
// d.date = +d.date;
// d.close = +d.close;
// });
// Scale the range of the data
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// append the x line
focus.append("line")
.attr("class", "x")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("y1", 0)
.attr("y2", height);
// append the y line
focus.append("line")
.attr("class", "y")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("x1", width)
.attr("x2", width);
// append the circle at the intersection
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "blue")
.attr("r", 4);
// place the value at the intersection
focus.append("text")
.attr("class", "y1")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "-.3em");
focus.append("text")
.attr("class", "y2")
.attr("dx", 8)
.attr("dy", "-.3em");
// place the date at the intersection
focus.append("text")
.attr("class", "y3")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "1em");
focus.append("text")
.attr("class", "y4")
.attr("dx", 8)
.attr("dy", "1em");
// append the rectangle to capture mouse
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.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;
focus.select("circle.y")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")");
focus.select("text.y1")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y2")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y3")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select("text.y4")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select(".x")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.attr("y2", height - y(d.close));
focus.select(".y")
.attr("transform",
"translate(" + width * -1 + "," +
y(d.close) + ")")
.attr("x2", width + width);
}
</script>
</body>
line is coming correctly but i m not able to set mouseover tooltip like above example..
I m facing error like invert fuction is not defined...
In the chart you linked to, he is using a time-scale for the x-axis (which has an invert-function). You are using an ordinal-scale (which do not have an invert-function).The invert-function is used to calculate the value on the x-axis for a given mouse-position.
A time-scale always has a corresponding x-value for each mouse-position (since it is continous, so no matter where your mouse is, you have a date-time for that position) while an ordinal scale does not have a corresponding x-value for all mouse-positions since it is discrete, i.e. what is the x-value when you have the mouse in-beteen for example w1 and w2?
So your solution would be to change to a time-scale (in which case you have to convert w1,w2,w3 e.t.c. to a date-time object).
Or, if you want to stick with your ordinal-scale, you have to remove the invert function. Since the invert-function is used to calculate the x-value for a given mouse-position, you have to create this logic by your self. Inspiration can be found in Inversion with ordinal scale. So replace var x0 = x.invert(d3.mouse(this)[0]) with
var xPos = d3.mouse(this)[0];
console.log("hovering at " + xPos);
var leftEdges = x.range();
var width = x.rangeBand();
var j;
for(j=0; xPos > (leftEdges[j] + width); j++) {}
//do nothing, just increment j until case fails
console.log("Clicked on " + x.domain()[j]);
var x0 = x.domain()[j];
I am a little new to D3 js.I need to align two graphs (bar and pie) side by side which will be displayed on a dashboard.When I use individual .html files for bar and pie charts,they work perfectly but the charts are getting overlapped when I combine them into a single .html file.
I have tried changing different parameters related to "svg" and corresponding x and y axes but to no avail.
There are two csv files(pie-data.csv,bar-data.csv) from where data will be picked.
Below is my code ::
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.arc text {
font: 10px sans-serif;
text-anchor: middle;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.ticket_count; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("pie-data.csv", type, function(error, data) {
if (error) throw error;
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.ticket_meter); });
g.append("text")
.attr("transform", function(d) { return "translate(" + labelArc.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.data.ticket_meter; });
});
function type(d) {
d.ticket_count = +d.ticket_count;
return d;
}
////////////////////////////////////////////////
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 150 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
d3.csv("bar-data.csv", function(error, data) {
data.forEach(function(d) {
d.issue_status = d.issue_status;
d.issue_count = +d.issue_count;
});
x.domain(data.map(function(d) { return d.issue_status; }));
y.domain([0, d3.max(data, function(d) { return d.issue_count; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.issue_status); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.issue_count); })
.attr("height", function(d) { return height - y(d.issue_count); });
});
</script>
</body>
</html>
Please suggest any pointers so that alignment can be done.Thanks in advance.
You are using the same variable twice:
var svg = d3.select("body").append("svg");
(and, besides that one, you are repeating some other variables that should be unique)
Appending the SVGs to the "body" is not the correct way, because when you append an SVG to the body the SVG is put at the end of the page, and you'll not be able to position them side by side.
A solution would be creating one div for each chart, with IDs #chart1 and #chart2 for instance, and then creating two variables:
var svg1 = d3.select("#chart1").append("svg");
And
var svg2 = d3.select("#chart2").append("svg");
Don't forget to change all other variables accordingly.
After the changes, use CSS to align the two divs side by side.
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.
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.