I want to create x-axis where I can set certain number of duplicated STRING values.
Here is example of data I could use for it (first letters of weekday names):
const chartData = [
{ xValue: 'M', yValue: 1 },
{ xValue: 'T', yValue: 2 },
{ xValue: 'W', yValue: 2 },
{ xValue: 'T', yValue: 4 },
{ xValue: 'F', yValue: 2 },
{ xValue: 'S', yValue: 1 },
{ xValue: 'S', yValue: 3 }];
Here is the code for creating bar-chart:
const chartTicks = 5;
const margin = { top: 30, right: 30, bottom: 50, left: 140 };
const yScaleMaxValuePercentage = 110;
const xValue = 'xValue';
const yValue = 'yValue';
const svg = d3.select('.bar-chart-horizontal');
const marginWidth = margin.left + margin.right;
const marginHeight = margin.top + margin.bottom;
const width = +svg.attr('width') - marginWidth;
const height = +svg.attr('height') - marginHeight;
const scaleX = d3.scaleBand().rangeRound([height, 0]);
const scaleY = d3.scaleLinear().rangeRound([0, width]);
const mainGroup = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
let paddingBetweenBars = 0.7;
function calculateScaleY(chartData) {
const maxValueY = d3.max(chartData, (d) => (d[yValue]));
return [0, Math.ceil(maxValueY * yScaleMaxValuePercentage / 100)];
}
function drawBarChart(chartData) {
// Calculating - X and Y axis scale
scaleY.domain(calculateScaleY(chartData));
scaleX.domain(chartData.map((d) => (d[xValue])))
.padding(paddingBetweenBars);
// Draw - Y axis
mainGroup.append('g')
.attr('class', 'axis axis--y')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom(scaleY).ticks(chartTicks));
// Draw - X axis
mainGroup.append('g')
.attr('class', 'axis axis--x')
.call(d3.axisLeft(scaleX))
.append('text')
.attr('transform', 'rotate(-90)')
.attr('text-anchor', 'end');
// Draw - Bars
mainGroup.append('g')
.selectAll('.bar-chart-horizontal .bar')
.data(chartData)
.enter().append('rect')
.attr('class', 'bar')
.attr('y', (d) => (scaleX(d[xValue])))
.attr('height', scaleX.bandwidth())
.attr('x', 0)
.attr('width', (d) => (scaleY(d[yValue])));
}
drawBarChart(chartData);
CodePen: http://codepen.io/Arthe/pen/qqRpgj
My problem is, that with current version of code, it creates two bars on the same label (they overlap each other), because we got double 'S' and double 'T' in the data. I want x-axis to have two different 'S' and 'T' (7 x-axis labels instead of 5). I tried some ideas from stackoverflow, but none of the answer let you use string values on the axis. Linear scale as far as I know, don't let you use strings. If I add IDs to data and use them as sorting variables, the bars dont overlap anymore but I have IDs on the x axis instead of strings. I looked on all scales d3js can provide and I didn't find better scale for it than ordinal one.
EDIT: Maybe its worth mentioning, that I don't know what type of strings I will get in data, and how many of them there will be, I just know that duplicated strings can't be stacked, but have separate bars.