I have a d3.js bar chart, but the X axis columns have no height, presumably because there is no data/scale for the Y axis. The last column should display.
The JSON:
[{"Domain":"Knowledge","Knowledge":0},{"Domain":"Problem Solving","problem_solving":0},{"Domain":"Skill","skill":0},{"Domain":"Transferable","transferable":100}]
The chart:
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 ")");
// load the data
d3.json("json/domains.json", function(error, data) {
// 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(dataset[0].map(function(d) { return d.x; }))
.rangeRoundBands([10, width-10], 0.35, 0);
var y = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { return d.y0 d.y; }); })])
.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("Disciplines");
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(dataset)
.enter().append("g")
.attr("class", "group")
.style("fill", function(d, i) { return colors[i]; });
// var svg = d3.select("svg");
var bar = groups.selectAll("g")
.data(function(d) { return d; })
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" x(d.x) ", 0)";
});
var sum=0;
bar.append("rect")
.attr("y", function(d) { return y(d.y0 d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 d.y); })
.attr('class', 'segment')
.attr("width", x.rangeBand())
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
columns = svg.append("g")
.selectAll("text").data(disciplines)
.enter().append("text")
.attr("x", function(d){
return x(d.key) x.rangeBand()/2
})
.attr("y", function (d) {
return y(d.values);
})
.attr("dy", "-0.7em")
.attr('style', 'font-size:11px')
.text( function (d){
return d3.format(".2f")(d.values) '%';
})
.style({fill: 'black', "text-anchor": "middle"});
// Draw legend
var legend = svg.selectAll(".legend")
.data(colors)
.enter().append("g")
.attr("class", "legend")
.attr('style', 'font-size:12px')
.attr("transform", function(d, i) {
return "translate(30," i * 19 ")";
});
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {return colors.slice().reverse()[i];});
legend.append("text")
.attr("x", width 5)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d, i) {
switch (i) {
case 0:
return "Knowledge";
case 1:
return "Problem Solving";
case 2:
return "Skill";
case 3:
return "Transferable";
}
});
});
I have another d3.js chart, which uses practically the same chart code as above and JSON format, just the data is different, columns and Y axis graduations show OK:
UPDATE
Changed 'Domain' key in the JSON to 'Dom' so as not to cause any conflict with the d3.js function .domain
(makes no difference to the chart though...):
JSON:
[{"Dom":"Knowledge","Knowledge":0},{"Dom":"Problem Solving","problem_solving":0},{"Dom":"Skill","skill":0},{"Dom":"Transferable","transferable":100}]
Chart:
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 ")");
// load the data
d3.json("json/domains.json", function(error, data) {
// 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.Dom,
y: d[lvl]
};
});
}));
var domains = d3.nest()
.key(function(d){return d.Dom})
.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(dataset[0].map(function(d) { return d.x; }))
.rangeRoundBands([10, width-10], 0.35, 0);
var y = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { return d.y0 d.y; }); })])
.range([height, 0]);
var colors = ["#50E0C8", "#f17950", "#C283D1", "#50BCF1"];
// 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)" )
.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(dataset)
.enter().append("g")
.attr("class", "group")
.style("fill", function(d, i) { return colors[i]; });
// var svg = d3.select("svg");
var bar = groups.selectAll("g")
.data(function(d) { return d; })
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" x(d.x) ", 0)";
});
var sum=0;
bar.append("rect")
.attr("y", function(d) { return y(d.y0 d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 d.y); })
.attr('class', 'segment')
.attr("width", x.rangeBand())
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
columns = svg.append("g")
.selectAll("text").data(domains)
.enter().append("text")
.attr("x", function(d){
return x(d.key) x.rangeBand()/2
})
.attr("y", function (d) {
return y(d.values);
})
.attr("dy", "-0.7em")
.attr('style', 'font-size:11px')
.text( function (d){
return d3.format(".2f")(d.values) '%';
})
.style({fill: 'black', "text-anchor": "middle"});
});
CodePudding user response:
Fixed some errors and simplified your code. See it working in the fiddle:
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 ")");
// load the data
const data = [{"Domain":"Knowledge","knowledge":0},{"Domain":"Problem Solving","problem_solving":0},{"Domain":"Skill","skill":0},{"Domain":"Transferable","transferable":100}];
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("Disciplines");
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"});
// Draw legend
var legend = svg.selectAll(".legend")
.data(colors)
.enter().append("g")
.attr("class", "legend")
.attr('style', 'font-size:12px')
.attr("transform", function(d, i) {
return "translate(30," i * 19 ")";
});
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {return colors.slice().reverse()[i];});
legend.append("text")
.attr("x", width 5)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d, i) {
switch (i) {
case 0:
return "Knowledge";
case 1:
return "Problem Solving";
case 2:
return "Skill";
case 3:
return "Transferable";
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div id="domains" />