I'm working on a D3 data visualization and I'm trying to get my first bar chart to disappear and then have a new one appear exactly where the last one was. My problem is the second one is getting overlayed right above the first one so everything gets muddled up. Any help would be greatly appreciated.
Here is my code:
var data = [{
"name": "text",
"value": 2,
},
{
"name": "text",
"value": 44,
},
{
"name": "text",
"value": 20,
},
{
"name": "text",
"value": 18,
},
{
"name": "text",
"value": 12,
},
{
"name": "text",
"value": 9,
},
{
"name": "text",
"value": 7,
},
{
"name": "text",
"value": 6,
},
{
"name": "text",
"value": 5,
},
{
"name": "text",
"value": 4,
},
];
var margin = {
top: 15,
right: 35,
bottom: 15,
left: 115
};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//var startBar2010 =
startBarChart.append("g").attr("class","bar2010");
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
//.attr("align","center")
.append("g")
.attr("transform", "translate(" + margin.left + "," +
margin.top + ")");
//.attr("transform", "translate(" + 200 + "," + (-500) + ")");
var x = d3.scale.linear()
.range([0, width])
.domain([0, d3.max(data, function (d) {
return d.value;
})]);
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], .1)
.domain(data.map(function (d) {
return d.name;
}));
//make y axis to show bar names
var yAxis = d3.svg.axis()
.scale(y)
//no tick marks
.tickSize(0)
.orient("left");
var gy = svg.append("g")
.attr("class", "y axis")
.transition().delay(delay*1).ease(d3.easeLinear).duration(1000)
.call(yAxis);
var bars = svg.selectAll(".bar")
.data(data)
.enter()
.append("g");
//append rects
bars.append("rect")
.attr("class", "bar")
.attr("x", -500)
.attr("y", -25)
.attr("width", 0)
.attr("height", 35)
.transition().delay(delay*1).ease(d3.easeLinear).duration(1000)
//.transition().delay(delay*1).duration(2500)
.attr("y", function (d) {
return y(d.name);
})
.attr("height", y.rangeBand())
.attr("x", 0)
.attr("width", function (d) {
return x(d.value);
})
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Do I Work ?");
bars.append("text")
.attr("class", "label")
.attr("y", -42)
.attr("x", -520)
.transition().delay(delay*1).ease(d3.easeLinear).duration(1000)
//y position of the label is halfway down the bar
.attr("y", function (d) {
return y(d.name) + y.rangeBand() / 2 + 4;
})
//x position is 3 pixels to the right of the bar
.attr("x", function (d) {
return x(d.value) + 3;
})
.text(function (d) {
return d.value;
});
I thought the following code would clear everything for the follow up bar chart
bars.selectAll("g")
//.transition().delay(delay*3).duration(1000)
.transition().delay(delay*1.7).duration(1000)
.style("opacity",0)
.call(endall, function() {
bars.selectAll("g")
.remove();
});
Here is second bar chart data and chart:
var dataTwo = [{
"name": "text",
"value": 2,
},
{
"name": "text",
"value": 44,
},
{
"name": "text",
"value": 20,
},
{
"name": "text",
"value": 18,
},
{
"name": "text",
"value": 12,
},
{
"name": "text",
"value": 9,
},
{
"name": "text",
"value": 7,
},
{
"name": "text",
"value": 6,
},
{
"name": "text",
"value": 5,
},
{
"name": "text",
"value": 4,
},
];
var margin = {
top: 15,
right: 35,
bottom: 15,
left: 115
};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//var startBar2010 =
startBarChart.append("g").attr("class","bar2010");
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
//.attr("align","center")
.append("g")
.attr("transform", "translate(" + margin.left + "," +
margin.top + ")");
//.attr("transform", "translate(" + 200 + "," + (-500) + ")");
var x = d3.scale.linear()
.range([0, width])
.domain([0, d3.max(dataTwo, function (d) {
return d.value;
})]);
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], .1)
.domain(dataTwo.map(function (d) {
return d.name;
}));
//make y axis to show bar names
var yAxis = d3.svg.axis()
.scale(y)
//no tick marks
.tickSize(0)
.orient("left");
var gy = svg.append("g")
.attr("class", "y axis")
.transition().delay(delay*2.1).ease(d3.easeLinear).duration(1000)
.call(yAxis);
// Update with new values
var bars = svg.selectAll(".bar")
.data(dataTwo)
.enter()
.append("g");
//append rects
bars.append("rect")
.attr("class", "bar")
.attr("x", -500)
.attr("y", -25)
.attr("width", 0)
.attr("height", 35)
.transition().delay(delay*2.1).ease(d3.easeLinear).duration(1000)
//.transition().delay(delay*1).duration(2500)
//.selection().delay(delay*1).duration(2500)
.attr("y", function (d) {
return y(d.name)
})
.attr("height", y.rangeBand())
.attr("x", 0)
.attr("width", function (d) {
return x(d.value)
});
bars.append("text")
.attr("class", "label")
.attr("y", -42)
.attr("x", -520)
.transition().delay(delay*2.1).ease(d3.easeLinear).duration(1000)
//y position of the label is halfway down the bar
.attr("y", function (d) {
return y(d.name) + y.rangeBand() / 2 + 4;
})
//x position is 3 pixels to the right of the bar
.attr("x", function (d) {
return x(d.value) + 3;
})
.text(function (d) {
return d.value;
});
Just as the combination of enter().append() is used in D3.js to create DOM elements to reflect dataset elements that don't yet exist in the DOM, likewise the exit().remove() combination is used to remove those DOM elements.
What you will want to do, then, is to have a DOM element acting as a container which you use as the root of your D3 manipulations. Generally, we have a div to which we add the chart's SVG - but you should know which element this is, whether body, a div or something else. Everything that you add into that container, should be removed by 2 steps:
Implementing your exit().remove() as described below.
Clearing your entire dataset currently bound to that set of elements.
This is a useful description. Mike Bostock (D3.js's author) has a diagram clarifying exactly what enter, exit and update mean; "elements" here means "DOM elements", while "data" means "data array elements":
Related
I am using D3.js to produce Sankey diagrams, and I'm not satisfied with the resulting connection between nodes, particularly when the total input of a node is different from its total output.
As an example:
// set the dimensions and margins of the data
var margin = { top: 10, right: 10, bottom: 10, left: 10 },
width = 300 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#graph").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 sankey diagram properties
var sankey = d3.sankey()
.nodeWidth(10)
.nodePadding(10)
.size([width, height]);
data = {
"nodes": [
{ "node": 0, "name": "A" },
{ "node": 1, "name": "B" },
{ "node": 2, "name": "C" }
],
"links": [
{ "source": 0, "target": 1, "value": 2 },
{ "source": 1, "target": 2, "value": 1 }
]
}
// Constructs a new Sankey generator with the default settings.
sankey
.nodes(data.nodes)
.links(data.links)
.layout(1);
// add in the links
svg.append("g")
.selectAll(".link")
.data(data.links)
.enter()
.append("path")
.attr("class", "link")
.attr("d", sankey.link())
.style("stroke-width", function (d) { return Math.max(1, d.dy); })
// add in the nodes
var node = svg.append("g")
.selectAll(".node")
.data(data.nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
// add the rectangles for the nodes
node.append("rect")
.attr("height", function (d) { return d.dy; })
.attr("width", sankey.nodeWidth())
// add in the title for the nodes
node.append("text")
.attr("x", -6)
.attr("y", function (d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function (d) { return d.name; })
.filter(function (d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start")
<body>
<style>
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
</style>
<div id="graph"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery#master/LIB/sankey.js"></script>
<script src="test.js"></script>
</body>
This produces:
But without chaning the input data I would like:
Meaning the node size is determined by the link value, but the link size matches both the input and the output nodes.
I am trying D3 to develop new barchart. This is my first try to d3
I followed one article Here and based on it I am trying to develop one barchart by writing below code.
My code look like
function get_data() {
console.log("create post is working!") // sanity check
return $.ajax({
url : "/group/guest/query/", // the endpoint
type : "GET", // http method
});
};
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()
.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("#chart").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 ajdata = get_data();
var k = [];
ajdata.success(function (data) {
var obj = jQuery.parseJSON(data);
obj.forEach(function(d) {
d.created_date = d.created_date;
d.jobs_fail = +d.jobs_fail;
k.push(d.created_date)
});
x.domain(obj.map(function(d) {
return d.date_created;
}));
y.domain([0, d3.max(obj, function(d) {
//alert(JSON.stringify(d.jobs_fail));
return d.jobs_fail;
})]);
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("Count");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.date_created);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.jobs_fail);
})
.attr("height", function(d) {
return height - y(d.jobs_fail);
});
function type(d) {
d.jobs_fail = +d.jobs_fail;
return d;
}
});
I am pulling the data form one ajax request and the ajax response looks like below.
[ { "date": "2017-12-28", "jobs_fail": 2, "jobs_resub": 7, "jobs_success": 18 }, { "date": "2017-12-27", "jobs_fail": 20, "jobs_resub": 31, "jobs_success": 50 }, { "date": "2017-12-26", "jobs_fail": 22, "jobs_resub": 27, "jobs_success": 49 }, { "date": "2017-12-25", "jobs_fail": 11, "jobs_resub": 8, "jobs_success": 18 }, { "date": "2017-12-24", "jobs_fail": 5, "jobs_resub": 2, "jobs_success": 4 }, { "date": "2017-12-23", "jobs_fail": 10, "jobs_resub": 16, "jobs_success": 23 }, { "date": "2017-12-22", "jobs_fail": 51, "jobs_resub": 54, "jobs_success": 97 } ]
When I ran this code I am getting the error.But my x axis dates (created_date) filed data is appearing on chart x axis.
Error: <rect> attribute y: Expected length, "NaN".
I understand this is something on y axis but I am not able to find any solution for it please guide me what might I am doing wrong here.
Hi All after spending lots of time and help from comment I am able to fix this issue.
So problem is in below piece of code.
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.date_created);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.jobs_fail);
})
.attr("height", function(d) {
return height - y(d.jobs_fail);
});
I am storing the parsed data into a variable called obj whereas I am using the data under .data since data has no value so it is not able to attach the values just replace data with obj and it works for me.
Thanks all for your support
I am beginner in D3 and don't know a lot about it.
I am currently trying to plot a 2D line on a graph using D3. I have been successfully able to plot the line, add axis , and even add zoom capabilities to the plot.
I am stuck in making the line hinged to y axis such that you can't just click on it and move it left or right (Currently if you would run the jsfiddle you could click on it and move the plotted line). I would still want to zoom in or out . But it should remain hinged to the y axis. Please let me know if this clarifies my issue.
Thanks!
Link to JS fiddle:
https://jsfiddle.net/adityap16/4sts8nfs/2/
Code
var data = [{
"mytime": "2015-12-01T23:10:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:15:00.000Z",
"value": 67
}, {
"mytime": "2015-12-01T23:20:00.000Z",
"value": 70
}, {
"mytime": "2015-12-01T23:25:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:30:00.000Z",
"value": 72
}, {
"mytime": "2015-12-01T23:35:00.000Z",
"value": 75
}, {
"mytime": "2015-12-01T23:40:00.000Z",
"value": 71
}, {
"mytime": "2015-12-01T23:45:00.000Z",
"value": 80
}, {
"mytime": "2015-12-01T23:50:00.000Z",
"value": 83
}, {
"mytime": "2015-12-01T23:55:00.000Z",
"value": 86
}, {
"mytime": "2015-12-02T00:00:00.000Z",
"value": 80
}, {
"mytime": "2015-12-02T00:05:00.000Z",
"value": 85
}];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
},
height = 200,
width = 900;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value";
var params1 = {
margin: margin,
height: height,
width: width,
color: color,
xaxis_param: xaxis_param,
yaxis_param: yaxis_param
};
draw_graph(data, params1);
function draw_graph(data, params) {
var make_x_axis = function() {
return d3.svg.axis()
.scale(x_scale)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function() {
return d3.svg.axis()
.scale(y_scale)
.orient("left")
.ticks(5);
};
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
var x_extent = d3.extent(data, function(d) {
return d[xaxis_param]
});
var y_extent = d3.extent(data, function(d) {
return d[yaxis_param]
});
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0, width]);
var y_scale = d3.scale.linear()
.domain([0, y_extent[1]])
.range([height, 0]);
var zoom = d3.behavior.zoom()
.x(x_scale)
.y(y_scale)
.on("zoom", zoomed);
//Line
var line = d3.svg.line()
.defined(function(d) {
return d[yaxis_param];
})
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(d[yaxis_param]);
});
var lineRef = d3.svg.line()
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(20);
});
var myChart = d3.select('body').append('svg')
.attr('id', 'graph')
.style('background', '#E7E0CB')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.call(zoom);
myChart.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vAxis = d3.svg.axis()
.scale(y_scale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(5);
var majorAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.day, 1)
.tickSize(-height)
.outerTickSize(0);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "x axis major")
.attr("transform", "translate(0," + height + ")")
.call(majorAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis);
var circlePoint = myChart.selectAll('circle')
.data(data)
.enter()
.append("circle");
var circleAttributes = circlePoint
.attr("cx", function (d) { return x_scale(d[xaxis_param]); })
.attr("cy", function (d) { return y_scale(d[yaxis_param]); })
.attr("r", 3)
.style("fill", "none")
.style("stroke", "red");
var clip = myChart.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = myChart.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr('class', 'line')
.attr("d", line)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
chartBody
.append('svg:path')
.datum(data)
.attr('class', 'line1')
.attr("d", lineRef)
.attr('stroke', 'blue')
.attr('stroke-width', 1)
.style("stroke-dasharray", ("3, 3"))
.attr('fill', 'none');
function zoomed() {
myChart.select(".x.axis").call(hAxis);
myChart.select(".y.axis").call(vAxis);
myChart.select(".x.axis.major").call(majorAxis);
myChart.select(".line")
.attr("class", "line")
.attr("d", line);
myChart.select(".line1")
.attr("class", "line1")
.attr("d", lineRef);
}
}
Add this .on("mousedown.zoom", null) to disable panning:
var myChart = d3.select('body').append('svg')
.attr('id', 'graph')
.style('background', '#E7E0CB')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.call(zoom)
.on("mousedown.zoom", null);//disable panning
working code here
I am trying to show a D3 bar chart with positive and negative values, but I cant get the domain to show both?
I also want to tell the graph to draw based on the current data after I have updated it, but it wont update?
this is my code
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 370 - margin.left - margin.right,
height = 220 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
function updateBarGraph() {
var dataForGraph3 = [
{
"asset": "1",
"value": val1
},
{
"asset": "2",
"value": val2
},
{
"asset": "3",
"value": val3
},
{
"asset": "4",
"value": val4
}
];
console.log("updateBarGraph");
console.log(dataForGraph3);
x.domain(dataForGraph3.map(function(d) { return d.asset; }));
y.domain([0, d3.max(dataForGraph3, function(d) { return d.value; })]);
var svg = d3.select(".expReturnBar").transition();
svg.select(".bar") // change the line
.duration(750)
.attr("d", dataForGraph3);
svg.select(".x.axis") // change the x axis
.duration(750)
.call(xAxis);
svg.select(".y.axis") // change the y axis
.duration(750)
.call(yAxis);
};
function drawBarGraph() {
var dataForGraph3 = [
{
"asset": "1",
"value": val1
},
{
"asset": "2",
"value": val2
},
{
"asset": "3",
"value": val3
},
{
"asset": "4",
"value": val4
}
];
console.log("drawBarGraph");
console.log(dataForGraph3);
var svg = d3.select(".expReturnBar").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(dataForGraph3.map(function(d) { return d.asset; }));
y.domain([0, d3.max(dataForGraph3, 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");
svg.selectAll(".bar")
.data(dataForGraph3)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.asset); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
function type(d) {
d.value = +d.value;
return d;
}
$scope.drawn = true;
};
$scope.drawn = false;
function drawGraphs() {
if(!$scope.drawn)
drawBarGraph();
else
updateBarGraph();
}
$scope.update = function(){
val1 = val1 + 10;
val2 = val2 + 10;
val3 = val3 + 10;
val4 = val4 + 10;
drawGraphs();
}
when i call update(), the first time it works.
but then after that it doesnt change anything.
If you want negative y values, you need to set the domain to include negative values. Right now, it looks like it only has non-negative values. It should probably be something like:
y.domain([d3.min(dataForGraph3, function(d) { return d.value; }), d3.max(dataForGraph3, function(d) { return d.value; })]);
You may also want to set the range to control where the points end up, but that's up to you. Have a look here: https://github.com/mbostock/d3/wiki/Quantitative-Scales
As for update not working, this won't work.
svg.select(".bar") // change the line
.duration(750)
.attr("d", dataForGraph3);
This won't update your data, it will put your data into an attribute "d". You need to update the x and y.
I need help with visually displaying JSON data using D3.JS. I can get the graphs to show but my problem is that the bars stack up ontop of each other instead of being translated into groups based on the categories they are displaying. Below you can find my code as well as a link to a screengrab of my current output as well as the JSON file im using.
link to screengrab:
http://tinypic.com/view.php?pic=15x6anl&s=8#.VH3C5HWSw8o
and here is my code:
$(document).ready(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.json("ronaldo.json", function(error, data) {
console.log(data);
var playerNames = []
data.forEach(function(d){playerNames.push(d.name)})
var attr = [];
data[0]['statistics']['2005'].forEach(function(d){return attr.push(d.attr)})
console.log(attr)
x0.domain(attr.map(function(d){return d}));
//x0.domain(data.map(function(d){return d['statistics']['2005']['attr']}));
x1.domain(playerNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d["statistics"]["2005"], 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("Units");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(+d['statistics']['2005']['attr']) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d['statistics']['2005']; })
.enter().append("rect")
.attr("class","bars")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d['attr']); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d['value']); })
.style("fill", function(d) { return color(d.attr);});
var legend = svg.selectAll(".legend")
.data(playerNames.slice())
.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; });
});
});
JSON Data:
[
{
"name": "Cristiano Ronaldo",
"age" : 28,
"team": "Real Madrid",
"statistics" : {
"2005" : [
{"attr" :"Appearances",
"value": 100},
{"attr" :"Goals",
"value": 92},
{"attr" :"Yellow Cards",
"value": 10},
{"attr" :"Red Cards",
"value": 1}
]
}
},
{
"name": "Lionel Messi",
"age" : 29,
"team": "Barcelona",
"statistics" : {
"2005" : [
{"attr" :"Appearances",
"value": 90},
{"attr" :"Goals",
"value": 87},
{"attr" :"Yellow Cards",
"value": 13},
{"attr" :"Red Cards",
"value": 43}
]
}
}
]
I don't understand why you have a x0 and a x1 scales but your issue is here.
You should have only one scale that you use in:
xAxis (be careful to override the scale of xAxis after you defined x1)
.attr("x", function(d) { return x1(d['attr']); })
I have made a small jsFiddle with the solution I suggested but since I don't know what you wanted to see exactly, I'm not sure it's perfect: http://jsfiddle.net/chrisJamesC/uzmur5kb/
All I did was: change the .attr("x", ...) line to:
.attr("x", function(d) { return x0(d['attr']); })