d3 transform scale date to x position? - javascript

I have a linear y scale with a time series x scale. I want to put an overlay that follows the x/y value (similar to http://bl.ocks.org/mbostock/3902569).
The issue is that I'm not able to transform to the proper x scale value; for example when I mouseover my chart it outputs (this data is correct):
{ y: 0.05, x: "2015-07-26 15:08:47" }
{ y: 0.05, x: "2015-07-26 15:08:47" }
{ y: 0.05, x: "2015-07-26 15:08:47" }
Now I want to use this data to draw a point at that location; the issue is that I cannot replicate the above bl.locks.org example, and the transform isn't able to use the x position as a date; so how can I transform that x date to the point on the chart?
My mousemove is below:
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height,0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var varea = d3.svg.area()
.defined(function(d) { return d.y != null; })
.x(function(d) { return x(parseDate(d.x)); })
.y0(height)
.y1(function(d) { return y(d.y); });
var svg = d3.select(".swatch").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 + ")");
x.domain(d3.extent(data, function(d) { return parseDate(d.x); }));
y.domain([0, d3.max(data, function(d) {
if (d.y >= 1) {
return d.y
}
return 1;
})]);
svg.append("path")
.attr("class", "area")
.attr("d", varea(data));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var focus = svg.append("g")
.attr("class", "focus")
.attr("display", "none");
focus.append("circle")
.attr("r", 4.5);
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em");
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() {
focus.style("display", null);
})
.on("mouseout", function() {
focus.style("display", "none");
})
.on("mousemove", function() {
var x0 = x.invert(d3.mouse(this)[0]);
var bisect = d3.bisector(function(d) { return parseDate(d.x); }).right;
var item = data[bisect(data, x0)];
focus.attr("transform", "translate(" + x(parseDate(item.x)) + "," + y(item.y) + ")");
focus.select("text").text(item.y);
console.log(x(parseDate(item.x)));
console.log(y(item.y));
});
This code produces errors like the following in the console:
Unexpected value translate(NaN,120) parsing transform attribute.
So, the question is how do I convert the date to a proper coordinate?

Alright, so there were a couple of problems with my code.
I wasn't parsing the x value as a date; so I started parsing it with parseDate (see sample code) and then passed it to the x scale; this allowed me to get proper location on the chart.
The second issue was that display wasn't be set properly (setting it to null in Firefox wasn't allowing it to appear). So I changed that to display: inline; and it started showing up on the chart.

Related

d3.js Bar Chart - Y Axis NaN

Getting NaN on the Y axis for a d3.js bar chart.
Question relates to this one .
The answer in that question has static data, which is identical to the Ajax JSON. See commented line for const data But the Ajax data is not working.
The data is loaded but the column with data has no height as there is no Y scale data.
Console log:
Error: <rect> attribute y: Expected length, "NaN".
Error: <rect> attribute height: Expected length, "NaN".
Error: <text> attribute y: Expected length, "NaN".
Chart with Ajax loaded data:
var margin = {top: 50, right: 135, bottom: 70, left: 80},
width = 1050 - margin.left - margin.right,
height = 540 - margin.top - margin.bottom;
var svg = d3.select("#domains")
.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 + ")");
//const data = [{"Domain":"Knowledge","Knowledge":0},{"Domain":"Problem Solving","problem_solving":0},{"Domain":"Skill","skill":0},{"Domain":"Transferable","transferable":100}];
d3.json("json/domains.json", function(error, data) {
const normalized = data.map(item => {
const name = item['Domain'];
const attr = name.toLowerCase().replace(' ', '_');
const value = item[attr];
return {name, value};
});
console.log('N: ', normalized);
/*
// Transpose the data into layers
var dataset = d3.layout.stack()(["Knowledge", "Problem Solving, Skill, Transferable"].map(function(lvl) {
return data.map(function(d) {
return {
x: d.Domain,
y: d[lvl]
};
});
}));
var disciplines = d3.nest()
.key(function(d){return d.Domain})
.rollup(function(leaves){
return d3.sum(leaves, function(d) {return d3.sum(d3.values(d))});
})
.entries(data);
*/
// Set x, y and colors
var x = d3.scale.ordinal()
.domain(normalized.map(item => item.name))
.rangeRoundBands([10, width-10], 0.35, 0);
const maxValue = normalized.reduce((max, item) => Math.max(max, item.value), 0);
var y = d3.scale.linear()
.domain([0, maxValue])
.range([height, 0]);
var colors = ["#83d1c4", "#f17950", "#838BD1", "#F150BE"];
// Define and draw axes
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width, 0, 0)
.tickFormat(function(d) {
return d;
});
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.outerTickSize(0)
d3.select('.y axis .tick:first-child').remove();
/*
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-0, 0])
.html(function(d) {
return d.y + '%';
})
svg.call(tip);
*/
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0,0)")
.call(yAxis);
svg.append("g")
.call(xAxis)
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("text")
.attr("x", 390 )
.attr("y", 480 )
.style("text-anchor", "middle")
.text("Domains");
svg.append("text")
.attr("x", -200 )
.attr("y", -40 )
.attr("transform", "rotate(-90)" )
.attr('style', 'font-size:12px')
.style("text-anchor", "middle")
.text("Percentage of Learning Events");
// Create groups for each series, rects for each segment
var groups = svg.selectAll("g.group")
.data(normalized)
.enter().append("g")
.attr("class", "group")
.style("fill", function(d, i) { return colors[i]; });
groups.append("rect")
.attr("y", function(d) { return y(d.value); })
.attr("x", d => x(d.name))
.attr("height", function(d) { return y(0) - y(d.value); })
.attr('class', 'segment')
.attr("width", x.rangeBand())
// .on('mouseover', tip.show)
// .on('mouseout', tip.hide);
columns = svg.append("g")
.selectAll("text")
.data(normalized)
.enter().append("text")
.attr("x", function(d){
return x(d.name) + x.rangeBand()/2
})
.attr("y", function (d) {
return y(d.value);
})
.attr("dy", "-0.7em")
.attr('style', 'font-size:11px')
.text( function (d){
return d3.format(".2f")(d.value) + '%';
})
.style({fill: 'black', "text-anchor": "middle"});
});
Chart with static data:
Although your dataset had an typo, which can break your current setup if you had the same in the json output. We can not be that sure if there is no data provided in example from actual json response, which can be different than what's in your const data example
const data = [{"Domain":"Knowledge","Knowledge":0},{"Domain":"Problem Solving","problem_solving":0},{"Domain":"Skill","skill":0},{"Domain":"Transferable","transferable":100}];
Try with lowercase "knowledge":0 which was printing the chart correctly on my screen
https://jsfiddle.net/978ync63/

D3 adding tooltip to multi-line chart

I am fairly new to javascript and D3, I am trying to create a tooltip that displays a vertical line and circles on that line along with the value of data in each line. any help would be greatly appreciated ...
here is what I have got so far
I am fairly new to javascript and D3, I am trying to create a tooltip that displays a vertical line and circles on that line along with the value of data in each line. any help would be greatly appreciated ...
here is what I have got so far
function init() {
var formatDate, dataset, header, xScale, yScale, xAxis, yAxis, svg, coalConsLine,
gasConsLine, hydroConsLine, oilConsLine, solarConsLine, windConsLine, toolTip, lineData;
//dimensions
const margin = { top: 30, right: 40, bottom: 70, left: 20 };
const width = 650 - margin.right - margin.left;
const height = 530 - margin.top - margin.bottom;
//format date
formatDate = d3.timeFormat("%Y");
//import data from csv file
d3.csv("Australian_Energy_Production_and_Consumption.csv", function (d) {
return {
//to create new Date object for each year
date: new Date(d.year),
//coal consumption
coalCons: parseFloat(d.coal_consumption),
//coal production
coalProd: parseFloat(d.coal_production),
//electricity generation
elecPrdo: parseFloat(d.electricity_generation),
//gas consumption
gasCons: parseFloat(d.gas_consumption),
//gas production
gasProd: parseFloat(d.gas_production),
//hydro consumption
hydroCons: parseFloat(d.hydro_consumption),
//oil consumption
oilCons: parseFloat(d.oil_consumption),
//oil production
oilProd: parseFloat(d.oil_production),
//solar energy consumption
solarCons: parseFloat(d.solar_consumption),
//wind energy consumption
windCons: parseFloat(d.wind_consumption)
}
}).then(function (data) {
dataset = data;
MultiLineChart(dataset);
});
function MultiLineChart() {
//chart base
svg = d3.select("body")
.append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//append header group
header = svg.append('g')
.attr("class", "chartHeader")
.attr("class", "mainHeader")
.attr("transform", "translate(23," + -margin.top * 0.5 + ")")
.append("text");
//append text to header group
header.append("tspan")
.text("Australian Energy Consumption by Energy Source");
header.append("tspan")
.attr("class", "subHeading")
.attr("x", 0)
.attr("y", 15)
.text("Measured in Terawatt hour (TWh) from 2000-2019")
xScale = d3.scaleTime()
.domain([
d3.min(dataset, function (d) { return d.date; }),
d3.max(dataset, function (d) { return d.date; })])
.nice() //makes scale end in round number, in this case will end in 2020 instead of 2019
.range([0, width]);
xAxis = d3.axisBottom()
.ticks(d3.timeYear.every(1))
.scale(xScale);
yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function (d) {
return Math.max(d.coalCons, d.gasCons, d.hydroCons, d.oilCons, d.solarCons, d.windCons)
})])
.nice()
.range([height, 0]);
yAxis = d3.axisLeft()
.ticks(10)
.scale(yScale);
svg.append("g")
.attr("class", "axis")
.attr("class", "Xaxis")
.attr("transform", "translate(" + margin.left + "," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + margin.left + ", 0)")
.call(yAxis);
//coal energy consumption line genetator
coalConsLine = d3.line()
.x(function (d) { return xScale(d.date); })
.y(function (d) { return yScale(d.coalCons); });
//Creating the coal energy consumption line
svg.append("path")
.datum(dataset)
.attr("class", "coalConsLine")
.attr("class", "consLines")
.attr("transform", "translate(" + margin.left + ", 0)")
.attr("d", coalConsLine)
.style("stroke", "#010E13");
//gas energy consumption line genetator
gasConsLine = d3.line()
.x(function (d) { return xScale(d.date); })
.y(function (d) { return yScale(d.gasCons); });
//Creating the gas energy consumption line
svg.append("path")
.datum(dataset)
.attr("class", "gasConsLine")
.attr("class", "consLines")
.attr("transform", "translate(" + margin.left + ", 0)")
.attr("d", gasConsLine)
.style("stroke", "#ffa600");
toolTip = d3.selectAll(".toolTip");
//define lineData
lineData = d3.select(this).data()[0];
function mouseover() {
toolTip
.style('left', d3.event.clientX + 10 + 'px')
.style('top', d3.event.clientY + 5 + 'px')
.style('opacity', 0.97)
//I don't know how to get the data value
toolTip.select('.year').html("year " + lineData.date);
}
function mousemove() {
toolTip
.style('left', d3.event.clientX + 13 + 'px')
.style('top', d3.event.clientY + 5 + 'px')
}
function mouseout() {
toolTip.style('opacity', 0)
}
d3.selectAll(".consLines")
.on("mouseover", mouseover)
.on('mousemove', mousemove)
.on('mouseout', mouseout);
}
}
window.onload = init;

Plot multiple lines and scatter points on the same chart using d3, and use the mouseover function to calculate distance

I want to plot multiple lines and scatter plot on the same d3 chart.And I also define a mouse over function to calculate the distance between the scatter points and the line. Here is my js code:
import measurement from '../datasets/measurement';
// Parse the date / time
var parseDate = d3.time.format("%e/%_m/%Y %H");
// Get the data
d3.csv("../datasets/Book1.csv", function(error, data) {
data.forEach(function (d) {
d.date = parseDate.parse(d.dateHour);
d.estPressure = +d.x_inf;
d.lowPressure = +d.m1std;
d.upPressure = +d.p1std;
});
console.log(data);
// Set the dimensions of the canvas / graph
var margin = {top: 20, right: 50, bottom: 30, left: 66},
body_width = parseInt(d3.select('body').style('width').replace('px','')),
width = body_width - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// 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 + ")");
// Set the ranges
var x = d3.time.scale()
.domain([parseDate.parse("1/5/2016 00"), parseDate.parse("14/5/2016 23")])
// .domain(data.date])
.nice(d3.time.week)
/*.domain(data.map(function (d) {
return d.date;
}))*/
.range([0, width]);
//.rangeRoundBands([0, width], 0.1);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format('%B %e %H:00'));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("text")
.attr("x", 1780)
.attr("y", 940)// text label for the x axis
.style("text-anchor", "end")
.text("Time");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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("pressure");
y.domain([0, d3.max(data, function (d) {
return d.upPressure;
})]);
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.estPressure);
});
// Draw line.
var linegraph = svg.selectAll("path.line").data([data], function (d) {
return d.date;
});
linegraph.attr('d', line).style("opacity", 1.0);
linegraph.enter().append("path")
.attr("class", "line")
.attr("d", line);
});
var data1 = measurement.map(function (d) {
Object.keys(d).forEach(function (key) {
d[key] = +d[key];
});
return d;
});
console.log(data1);
// Add the scatterplot
svg.selectAll(".dot")
.data(data1)
.enter().append("circle")
.attr("r", 4)
.attr("cx", function (d) {
return x(d.t);
})
.attr("cy", function (d) {
return y(d.est);
})
.on("mouseover", function (d) { //hover event
tooltip.transition()
.duration(100)
.style("opacity", .9)
.style("left", (d3.event.pageX + 20) + "px")
.style("top", (d3.event.pageY - 30) + "px");
var dist = 0, lowerbound;
data.forEach(function (n) {
if (n.t === d.t) {
dist = d.est - n.pressure ;
if (dist < 0) dist = dist * -1;
}
else if (n.time < d.t) { // linear interpolation for the t
lowerbound = n;
}
});
tooltip.html("<h1>" + "X: " + d.t + " Y: " + d.x + " distance:" + dist.toFixed(3) + "</h1>");
})
.on("mouseout", function (d) {
tooltip.transition()
.duration(200)
.style("opacity", 0);
});
And my csv data for the line chart is like this:
tHour,x_inf,p1std,m1std,dateHour
1,10,10.3,9.2,1/5/2016 00
2,12,16.8,7.2,1/5/2016 01
3,14,21.2,6.8,1/5/2016 02
4,15,19.8,10.2,1/5/2016 03
5,14.5,16.9,12.1,1/5/2016 04
6,18,22.96,13.04,1/5/2016 05
My jason data for the scatter points are like(measurement):
{
"t": 1,
"est": 1
},
{
"t": 3,
"est": 12
},
{
"t": 5,
"est": 14
},
{
Could anyone help me about the code? I am new to d3...And I just can plot only one line here using the dateHour as x and x_inf as y in the csv data. I want to use dateHour data as x and plot three lines using x_inf,p1std,m1std values. It would be so nice if you could also help me with the scatter points.

Plotting a line graph along with Bar graph in d3js. Issue with Date

I'm learning d3js using various examples found online.
I've been trying to plot a chart with dual Y axis and an X-axis. The Y axis on the left side would plot a bar chart against the X-axis and the Y-axis on the right side would plot a line chart against X-axis. The Bar graph plots as exactly as required but the line graph does not. The X-axis is date (2015-10-15 04:10). Following this example.
The code I wrote
var margin = {top: 50, right: 50, bottom: 100, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%m/%d/%Y %H:%M:%S").parse;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var yTxnVol = d3.scale.linear().range([height, 0]);
var yResTime = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(yTxnVol)
.orient("left")
var yAxis2 = d3.svg.axis()
.scale(yResTime)
.orient("right")
.ticks(10);
var svg = d3.selectAll("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("../res/data.csv", function(error, data) {
data.forEach(function(d) {
d.AVRG_RESP_TIME = +d.AVRG_RESP_TIME;
d.TXN_VOL = +d.TXN_VOL;
});
x.domain(data.map(function(d) { return d.TYM; }));
yTxnVol.domain([0, d3.max(data, function(d) { return d.TXN_VOL+50; })]);
yResTime.domain([0, d3.max(data, function(d) { return d.AVRG_RESP_TIME+50; })]);
var minDate = d3.min(data, function(d){return d.TYM});
var maxDate = d3.max(data, function(d){ return d.TYM});
var xScale = d3.time.scale().range([0,width]);//.domain([minDate, maxDate]);
xScale.domain(d3.extent(data, function(d) { return new Date(d.TYM); }));
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)
svg.append("g")
.attr("class","y axis")
.attr("transform","translate("+width+ ", 0)")
.call(yAxis2)
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "yhover")
.attr("x", function(d) { return x(d.TYM); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return yTxnVol(d.TXN_VOL); })
.attr("height", function(d) { return height - yTxnVol(d.TXN_VOL); })
var line = d3.svg.line()
.x(function(d) { return xScale(new Date(d.TYM));})
.y(function(d) { return d.AVRG_RESP_TIME; });
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
The Output Trying to make this to a meaningful line graph. Got NaN error while formatting the dates.
Could someone help me to make this a proper line graph ?
The csv data sample
TYM, AVRG_RESP_TIME, TXN_VOL
2015-10-15 04:00:00, 12, 170
2015-10-15 04:10:00, 18, 220
2015-10-15 04:20:00, 28, 251
2015-10-15 05:00:00, 19, 100
First, fix your csv file. It is improperly formatted and should not have spaces after the comma.
Second, You are trying to mix an ordinal scale and a time scale for you xAxis. This isn't going to work. For your use case, just stick with time.
Here's a reworking of your code with explanatory comments:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var margin = {
top: 50,
right: 50,
bottom: 100,
left: 50
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
// x scale should be time and only time
var x = d3.time.scale().range([0, width]);
var yTxnVol = d3.scale.linear().range([height, 0]);
var yResTime = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(yTxnVol)
.orient("left")
var yAxis2 = d3.svg.axis()
.scale(yResTime)
.orient("right")
.ticks(10);
var svg = d3.selectAll("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) {
var data = [{"TYM":"2015-10-15 04:00:00","AVRG_RESP_TIME":"12","TXN_VOL":"170"},{"TYM":"2015-10-15 04:10:00","AVRG_RESP_TIME":"18","TXN_VOL":"220"},{"TYM":"2015-10-15 04:20:00","AVRG_RESP_TIME":"28","TXN_VOL":"251"},{"TYM":"2015-10-15 05:00:00","AVRG_RESP_TIME":"19","TXN_VOL":"100"}];
// just make TYM a date and keep it as a date
data.forEach(function(d) {
d.TYM = parseDate(d.TYM);
d.AVRG_RESP_TIME = +d.AVRG_RESP_TIME;
d.TXN_VOL = +d.TXN_VOL;
});
// get our min and max date in milliseconds
// set a padding around our domain of 15%
var minDate = d3.min(data, function(d){
return d.TYM;
}).getTime();
var maxDate = d3.max(data, function(d){
return d.TYM;
}).getTime();
var padDate = (maxDate - minDate) * .15;
x.domain([new Date(minDate - padDate), new Date(maxDate + padDate)]);
yTxnVol.domain([0, d3.max(data, function(d) {
return d.TXN_VOL + 50;
})]);
yResTime.domain([0, d3.max(data, function(d) {
return d.AVRG_RESP_TIME + 50;
})]);
// set an intelligent bar width
var barWidth = (width / x.ticks().length) - 20;
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)
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxis2)
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "yhover")
.attr("x", function(d) {
// center bar on time
return x(d.TYM) - (barWidth / 2);
})
.attr("width", barWidth)
.attr("y", function(d) {
return yTxnVol(d.TXN_VOL);
})
.attr("height", function(d) {
return height - yTxnVol(d.TXN_VOL);
})
.style("fill","orange");
var line = d3.svg.line()
.x(function(d) {
return x(d.TYM);
})
.y(function(d) {
return d.AVRG_RESP_TIME;
});
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.style("fill","none")
.style("stroke","steelblue")
.style("stoke-width","3px");
// });
</script>
</body>
</html>
The issue with the line graph filling with black was due to improper css. The new css property.
.line {
fill: none;
stroke: darkgreen;
stroke-width: 2.5px;
}
For the dates I formatted it to (%Y-%m-%d %H:%M) format and it worked.

how to left align ticks in d3 bar chart

i created a stacked bar graph.
on the y axis side i have ticks with varying lengths.
what i am trying to accomplish is to align the text in the tick to the left.
this is my example:http://jsfiddle.net/2khbceut/2/
html
<title>Diverging Stacked Bar Chart with D3.js</title>
<body>
<div id="figure" align="center" style="margin-bottom: 50px;"></div>
</body>
javascript
$(document).ready(getTopolegy());
function getTopolegy(){
var data = null;
var links = parseTopology(data);
createChart(links);
}
function parseTopology(data){
var links=[{1:5,2:5,3:10,N:20,link_name: "Link CHGIL21CRS-SFXCA21CRS"},
{1:5,2:5,3:10,N:20,link_name: "Link NYCNY21CRS-NYCNY22CRS"}];
return links;
}
function jsonNameToId(name){
switch (allocated_priority) {
case "allocated_priority":
return 1;
case "allocated_default":
return 2;
case "spare_capacity":
return 3;
case "total":
return "N";
default:
return 999;
}
}
function createChart(data){
var margin = {top: 50, right: 20, bottom: 10, left: 210},
width = 1000 - margin.left - margin.right,
height = 100 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], .3);
var x = d3.scale.linear()
.rangeRound([0, width]);
var color = d3.scale.ordinal()
.range(["#cccccc", "#92c6db", "#086fad"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var svg = d3.select("#figure").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id", "d3-plot")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(["Allocated Priority %", "Allocated Default %", "Spare Capacity %"]);
// d3.csv("js/raw_data.csv", function(error, data) {
data.forEach(function(d) {
d["Allocated Priority %"] = +d[1]*100/d.N;
d["Allocated Default %"] = +d[2]*100/d.N;
d["Spare Capacity %"] = +d[3]*100/d.N;
var x0 = 0;
var idx = 0;
d.boxes = color.domain().map(function(name) { return {name: name, x0: x0, x1: x0 += +d[name], N: +d.N, n: +d[idx += 1]}; });
});
var min_val = d3.min(data, function(d) {
return d.boxes["0"].x0;
});
var max_val = d3.max(data, function(d) {
return d.boxes["2"].x1;
});
x.domain([min_val, max_val]).nice();
y.domain(data.map(function(d) { return d.link_name; }));
svg.append("g")
.attr("class", "x axis")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
var vakken = svg.selectAll(".Link")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(0," + y(d.link_name) + ")"; });
var bars = vakken.selectAll("rect")
.data(function(d) { return d.boxes; })
.enter().append("g").attr("class", "subbar");
bars.append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.x0); })
.attr("width", function(d) { return x(d.x1) - x(d.x0); })
.style("fill", function(d) { return color(d.name); });
bars.append("text")
.attr("x", function(d) { return x(d.x0); })
.attr("y", y.rangeBand()/2)
.attr("dy", "0.5em")
.attr("dx", "0.5em")
.style("font" ,"10px sans-serif")
.style("text-anchor", "begin")
.text(function(d) { return d.n !== 0 && (d.x1-d.x0)>3 ? d.n : "" });
vakken.insert("rect",":first-child")
.attr("height", y.rangeBand())
.attr("x", "1")
.attr("width", width)
.attr("fill-opacity", "0.5")
.style("fill", "#F5F5F5")
.attr("class", function(d,index) { return index%2==0 ? "even" : "uneven"; });
svg.append("g")
.attr("class", "y axis")
.append("line")
.attr("x1", x(0))
.attr("x2", x(0))
.attr("y2", height);
var startp = svg.append("g").attr("class", "legendbox").attr("id", "mylegendbox");
// this is not nice, we should calculate the bounding box and use that
var legend_tabs = [0, 150, 300];
var legend = startp.selectAll(".legend")
.data(color.domain().slice())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + legend_tabs[i] + ",-45)"; });
legend.append("rect")
.attr("x", 0)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", 22)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "begin")
.style("font" ,"10px sans-serif")
.text(function(d) { return d; });
d3.selectAll(".axis path")
.style("fill", "none")
.style("stroke", "#000")
.style("shape-rendering", "crispEdges")
d3.selectAll(".axis line")
.style("fill", "none")
.style("stroke", "#000")
.style("shape-rendering", "crispEdges")
var movesize = width/2 - startp.node().getBBox().width/2;
d3.selectAll(".legendbox").attr("transform", "translate(" + movesize + ",0)");
// });
}
as can be seen the current positioning of the tick text is to the right.
i tried the following idea:
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("text")
.style("text-anchor", "start");
but it did not position the ticks in the desired alignment.
any ideas?
You can make the Y axis right-oriented, which will have the effect of positioning all the labels to the right of the axis, left-aligning them:
var yAxis = d3.svg.axis()
.scale(y)
.orient("right")// <- 1st step
At that point the labels would disappear, because they'll get covered up by the bars of the graph.
But then you can shift all those left-aligned labels some constant distance in the negative X direction, such that they're back on the left side of the Y axis, but still left-aligned the way you wanted. tickPadding() is a way to shift them:
var yAxis = d3.svg.axis()
.scale(y)
.orient("right")
.tickPadding(-180)
Here's your example, modified with the above: http://jsfiddle.net/2khbceut/3/
Maybe hardcoding the -180 is ok for you. If you need that amount to be dynamic, you can compute it using getBBox() on each text element of the axis and taking the maximum width to be the negative offset.
You can set the text-anchor to "start" and adjust the x position with translate, I added the code below in the chart model "boxPlotChart.js"
g.select('.nv-y.nv-axis').selectAll('.tick').selectAll('text')
.style('text-anchor','start')
.attr('transform', function(d,i,j) { return 'translate(-14,0)' });
g.select('.nv-y.nv-axis').selectAll('.nv-axisMaxMin').selectAll('text')
.style('text-anchor','start')
.attr('transform', function(d,i,j) { return 'translate(-16,0)' });

Categories

Resources