score:0
Your problem is with the offset of the bars from each other; if you hard-code a value, e.g. using translate(0,29)
, you are going to be in trouble when the chart data changes, and that makes the bars change size, too. To prevent that happening, set the translate value relative to the size of the bar:
//Appends first bar
var bars = categoryGroup.append("rect")
.attr("width", function(d) { return xScale(d.num); })
.attr("height", y0.rangeBand()/2.5 )
.attr("class", "g-num")
var bars2 = categoryGroup.append("rect")
.attr("width", function(d) { return xScale(d.num2); })
.attr("height", y0.rangeBand()/2.5 )
.attr("class", "g-num2")
.attr("transform", "translate(0," + ( y0.rangeBand()/2.5 ) + ")");
This way, no matter how many or how few bars you have in the chart, the offset of bars2
will always be the same size as the height of the bars, i.e. y0.rangeBand()/2.5
.
I'd advise you to standardise the bar label position in a similar manner, but add in a fixed y
offset using the dy
attribute:
//Appends first bar labels
var barLabels = labelGroup.append("text")
.text(function(d) {return d.num;})
.attr("x", function(d) { return xScale(d.num) - 20; })
.attr("y", y0.rangeBand()/2.5 ) // note: use 2.5, rather than 2.65
.attr('dy', '-0.35em') // fixed y offset, set relative to the text size
.attr("class", "g-labels");
//Appends second bar labels
var barLabels2 = labelGroup.append("text")
.text(function(d) {return d.num2;})
.attr("x", function(d) { return xScale(d.num2) - 20; })
.attr("y", y0.rangeBand()/1.25 )
.attr('dy', '-0.35em') // fixed y offset
.attr("class", "g-labels");
Here's your full example:
/* ----- Data ----- */
var json_data = {"headers":["Month","Country","Number"],"rows":[["2018-05-01 00:00:00.0","Germany",19],["2018-05-01 00:00:00.0","United Kingdom",23],["2018-04-01 00:00:00.0","Germany",21],["2018-04-01 00:00:00.0","United Kingdom",129] ]};
var dataRows = json_data.rows;
/* ----- !Data ----- */
/* ----- Functions ----- */
//Create dictionary function (transformed JSON)
createDict = (data) => {
let groups = data.reduce((acc, arr) => {
if (acc.hasOwnProperty(arr[1])) {
acc[arr[1]].push(arr);
} else {
acc[arr[1]] = [arr];
}
return acc;
}, {});
let results = [];
for (let g in groups) {
let obj = {Value: g};
let a = groups[g][0];
let b = groups[g][1];
if (a[0] <= b[0]) {
obj.num = a[2];
obj.num2 = b[2];
} else {
obj.num = b[2];
obj.num2 = a[2];
}
results.push(obj);
}
return results;
}
//Returns unique values of a specific object of a JSON string
uniqueValues = (data,objectNum) => {
var uniqueValues = [];
data.forEach(function(item) {
var value = item[objectNum];
if (uniqueValues.indexOf(value) !== -1)
return false;
uniqueValues.push(value);
});
return uniqueValues;
}
//Chart creation function
createChart = (data) => {
//Margin conventions
console.log(data)
var margin = {top: 10, right: 50, bottom: 20, left: 70};
var widther = window.outerWidth;
var width = widther - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
//Appends the svg to the chart-container div
var svg = d3.select(".g-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 + ")");
//Creates the xScale
var xScale = d3.scale.linear()
.range([0,width]);
//Creates the yScale
var y0 = d3.scale.ordinal()
.rangeBands([height, 0], 0.2)
.domain(uniqueValues);
console.log(d3.scale.ordinal().rangeBands([height, 0], 0.2) );
//.domain(["Spain", "UK", "Germany", "France", "Italy"]);
//Defines the y axis styles
var yAxis = d3.svg.axis()
.scale(y0)
.orient("left");
//Defines the y axis styles
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickFormat(function(d) {return d; })
//Change axis values for percentage
//.tickFormat(function(d) {return d + "%"; })
.tickSize(height)
.ticks(numTicks(width));
//FORMAT data
data.forEach(function(d) {
d.num = +d.num;
});
//Sets the max for the xScale
var maxX = d3.max(data, function(d) { return d.num; });
//Defines the xScale max
xScale.domain([0, maxX ]);
//Appends the y axis
var yAxisGroup = svg.append("g")
.attr("class", "y axis")
.call(yAxis);
//Appends the x axis
var xAxisGroup = svg.append("g")
.attr("class", "x axis")
.call(xAxis);
//Binds the data to the bars
var categoryGroup = svg.selectAll(".g-category-group")
.data(data)
.enter()
.append("g")
.attr("class", "g-category-group")
.attr("transform", function(d) {
return "translate(0," + y0(d.Value) + ")";
});
//Appends first bar
var bars = categoryGroup.append("rect")
.attr("width", function(d) { return xScale(d.num); })
.attr("height", y0.rangeBand()/2.5 )
.attr("class", "g-num")
// .attr("transform", "translate(0,4)");
//Appends second bar
var bars2 = categoryGroup.append("rect")
.attr("width", function(d) { return xScale(d.num2); })
.attr("height", y0.rangeBand()/2.5 )
.attr("class", "g-num2")
.attr("transform", "translate(0," + ( y0.rangeBand()/2.5 ) + ")");
//Binds data to labels
var labelGroup = svg.selectAll("g-num")
.data(data)
.enter()
.append("g")
.attr("class", "g-label-group")
.attr("transform", function(d) {
return "translate(0," + y0(d.Value) + ")";
});
//Appends first bar labels
var barLabels = labelGroup.append("text")
.text(function(d) {return d.num;})
.attr("x", function(d) { return xScale(d.num) - 20; })
.attr("y", y0.rangeBand()/2.5 )
.attr('dy', '-0.35em')
.attr("class", "g-labels");
//Appends second bar labels
var barLabels2 = labelGroup.append("text")
.text(function(d) {return d.num2;})
.attr("x", function(d) { return xScale(d.num2) - 20; })
.attr("y", y0.rangeBand()/1.25 )
.attr('dy', '-0.35em')
.attr("class", "g-labels");
//Appends chart source
d3.select(".g-source-bold")
.text("SOURCE: ")
.attr("class", "g-source-bold");
d3.select(".g-source-reg")
.text("Chart source info goes here")
.attr("class", "g-source-reg");
//RESPONSIVENESS
d3.select(window).on("resize", resized);
function resized() {
//new margin
var newMargin = {top: 10, right: 80, bottom: 20, left: 50};
//Get the width of the window
var w = d3.select(".g-chart").node().clientWidth;
console.log("resized", w);
//Change the width of the svg
d3.select("svg")
.attr("width", w);
//Change the xScale
xScale
.range([0, w - newMargin.right]);
//Update the bars
bars
.attr("width", function(d) { return xScale(d.num); });
//Update the second bars
bars2
.attr("width", function(d) { return xScale(d.num2); });
//Updates bar labels
barLabels
.attr("x", function(d) { return xScale(d.num) - 20; })
.attr("y", y0.rangeBand()/2.65 )
//Updates second bar labels
barLabels2
.attr("x", function(d) { return xScale(d.num2) - 20; })
.attr("y", y0.rangeBand()/1.25 )
//Updates xAxis
xAxisGroup
.call(xAxis);
//Updates ticks
xAxis
.scale(xScale)
.ticks(numTicks(w));
};
//}
//Determines number of ticks base on width
function numTicks(widther) {
if (widther <= 400) {
return 4
console.log("return 4")
}
else {
return 10
console.log("return 5")
}
}
}
/* ----- !Functions ----- */
/* ----- Main ----- */
var data = createDict(dataRows);
//Calculate unique Values
var uniqueValues = uniqueValues(dataRows,1);
createChart(data);
/* ----- !Main ----- */
/*css to go here*/
@import url(https://fonts.googleapis.com/css?family=Karla);
body {
font-family: 'Karla', sans-serif;
font-size: 12px;
}
.g-hed {
text-align: left;
text-transform: uppercase;
font-weight: bold;
font-size:22px;
margin: 3px 0;
}
.g-source-bold {
text-align: left;
font-size:10px;
font-weight: bold;
}
.g-source {
margin: 10px 0;
}
.g-source-bold {
text-align: left;
font-size:10px;
}
.g-intro {
font-size: 16px;
margin: 0px 0px 10px 0px;
}
.g-num {
fill:#124;
}
.g-num2 {
fill:#ccc;
}
.g-labels {
fill: white;
font-weight: bold;
font-size: 13px;
}
.axis line {
fill: none;
stroke: #ccc;
stroke-dasharray: 2px 3px;
shape-rendering: crispEdges;
stroke-width: 1px;
}
.axis text {
font-size: 13px;
pointer-events: none;
fill: #7e7e7e;
}
.domain {
display: none;
}
.y.axis text {
text-anchor: end !important;
font-size:14px;
fill: #000000;
}
.y.axis line {
display: none;
}
.g-baseline line {
stroke:#000;
stroke-width: 1px;
stroke-dasharray:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<body>
<h5 class="g-hed"></h5>
<p class="g-intro"></p>
<div class="g-chart"></div>
<div class="g-source"><span class="g-source-bold"></span><span class="g-source-reg"></span></div>
</div>
</body>
Source: stackoverflow.com
Related Query
- D3 Horizontal grouped stacked chart bars overlap for a small number of values
- How do I set the X values for a singled stacked horizontal bar chart using d3.js?
- If condition never met and hence my bars in a simple bar chart are always blue, while I want them to be red for values below a certain number
- Transition for grouped bar chart in d3 when updating the data values
- draw horizontal lines for bars in nvd3 multi bar chart
- d3 bar chart align bars on ticks for differing number of elements
- Unable to show the tooltip values for stacked area chart in a single tooltip
- how to display bar values in horizontal stacked bar chart
- d3js - Stacked Bar Chart in Horizontal Axis - How do I set x so the bars are seperated?
- D3 fill for a horizontal stacked bar chart in Angular with typeScript: .attr("fill", ..) gets error "No overload matches this call" in VSC
- d3 - Update Width and X for smooth transition in Horizontal Stacked Bar Chart
- D3 v3 - String values as x-axis domain for stacked chart not working
- D3 V4 how to force Label of stacked bars to visible for small bars? please reply I'm really struggling for it
- Bars chart for different number of bars in D3.js
- Y and Height Values for Stacked Bar Chart in D3
- Differentiating between bars in tooltip for stacked bar chart
- How can I keep tick marks from repeating when I have a small number of dates on an nvd3 chart
- d3.js - group 2 data values in a stacked bar chart
- Special donut chart with different rings/arcs for positive and negative values
- How to display values in Stacked Multi-bar chart - nvd3 Graphs
- Adding Error Bars to Grouped Bar Chart with D3.js
- Return multiple values from a crossfilter dimension for a pie chart
- How to add space between bars in a grouped bar chart in a nvd3 grouped multibar chart?
- d3.js stacked bar chart with positive and negative values
- How to modify axis labels in d3 for a stacked bar chart when the axis labels are mapped as part of the scale's domain
- NVD3.js: Stacked and grouped bar chart with two y-axis
- x axis labels overlapping for grouped category bar chart in d3
- Javascript manipulate data into array of object for d3 stacked chart
- Preview d3 bar chart such that it sorted by values for each x value
- Number formatting functions: What algorithm is used for rounding values ending in 5?
More Query from same tag
- D3.js - Load data from CSV file and use it outside function call
- access current attributes in d3 functions
- Drawing parallel coordinates for random selection of data
- How to find the highest attribute in a dataset, then display the "name" associated with that
- d3.js : very simple mouse interaction
- Only one defined value returned by d3.csv
- How to show values stacked bar chart utilizing dc.js and d3.js?
- D3 x-Axis not showing correctly
- d3 node sub structure/styling based on data attribute
- How do I make a simple d3 chart with Firebase data?
- D3.js: text attributes not being appended correctly?
- what's the absolute shortest d3 area example?
- sort data for d3 stacked bar chart
- D3- multiple radial progress charts
- d3.js Dendrogram: How to toggle visibility of nodes by click
- Defining Regions in a US Map Using D3.js
- Update indexes when deleting nodes
- d3 javascript click function call
- why is d3 each() function only iterating through first item in list?
- Can I use c3.js / nvd3.js in angular 2.0 beta ? import seems incompatible with system.js
- Troubleshooting post topojson installation
- How to make labels appear only when the chart is zoomed in
- d3 cross-linked mouseOver nodes
- visualization created using dc.js not rendering the y-axis data correctly
- c3.js bar, spline charts
- Suggestions for data mash-up development platform
- D3.js 'Pie Charts Labels' Overlapping
- scatter plot d3.js freecodecamp pronect having trouble with yscale displaying minutes
- Can i passed date string directly to d3 bar chart data?
- d3.js bubble chart, mousover and mouseout events only working first time