score:15
This is part of Chart.js 2.1 now! The chart type is horizontalBar
(with a lower case h).
var config = {
type: 'horizontalBar',
data: {
...
Fiddle - http://jsfiddle.net/gpxjohup/
Original Answer
Preview
Script
Most of this code is a copy of the code for bar
from the Chart.js library with x / y and width / height swapped. Thanks to @ZachPanzarino for helping with the axis labels!
Chart.defaults.HorizontalBar = {
hover: {
mode: "single"
},
scales: {
yAxes: [{
position: 'left',
type: "category",
categoryPercentage: 0.8,
barPercentage: 1,
gridLines: { offsetGridLines: true }
}],
xAxes: [{
ticks: {
beginAtZero: true
},
position: 'bottom',
type: "linear",
}],
},
};
Chart.controllers.HorizontalBar = Chart.controllers.bar.extend({
updateElement: function updateElement(rectangle, index, reset, numBars) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var xScalePoint;
if (xScale.min < 0 && xScale.max < 0) {
xScalePoint = xScale.getPixelForValue(xScale.max);
} else if (xScale.min > 0 && xScale.max > 0) {
xScalePoint = xScale.getPixelForValue(xScale.min);
} else {
xScalePoint = xScale.getPixelForValue(0);
}
Chart.helpers.extend(rectangle, {
_chart: this.chart.chart,
_xScale: xScale,
_yScale: yScale,
_datasetIndex: this.index,
_index: index,
_model: {
x: reset ? xScalePoint : this.calculateBarX(index, this.index),
y: this.calculateBarY(index, this.index),
label: this.chart.data.labels[index],
datasetLabel: this.getDataset().label,
base: this.calculateBarBase(this.index, index),
height: this.calculateBarHeight(numBars),
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth),
},
// override the draw and inRange functions because the one in the library needs width (we only have height)
draw: function() {
var ctx = this._chart.ctx;
ctx.fillStyle = this._view.backgroundColor;
ctx.fillRect(this._view.base, this._view.y - this._view.height / 2, this._view.x - this._view.base, this._view.height);
ctx.strokeStyle = this._view.borderColor;
ctx.strokeWidth = this._view.borderWidth;
ctx.strokeRect(this._view.base, this._view.y - this._view.height / 2, this._view.x - this._view.base, this._view.height);
},
inRange: function (mouseX, mouseY) {
var vm = this._view;
var inRange = false;
if (vm) {
if (vm.x < vm.base) {
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
} else {
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
}
}
return inRange;
}
});
rectangle.pivot();
// the animation progresses _view values from their current value to the _model value
rectangle._view.x = rectangle._model.base;
},
calculateBarBase: function (datasetIndex, index) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var base = 0;
if (xScale.options.stacked) {
var value = this.chart.data.datasets[datasetIndex].data[index];
if (value < 0) {
for (var i = 0; i < datasetIndex; i++) {
var negDS = this.chart.data.datasets[i];
if (Chart.helpers.isDatasetVisible(negDS) && negDS.xAxisID === xScale.id) {
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
}
}
} else {
for (var j = 0; j < datasetIndex; j++) {
var posDS = this.chart.data.datasets[j];
if (Chart.helpers.isDatasetVisible(posDS) && posDS.xAxisID === xScale.id) {
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
}
}
}
return xScale.getPixelForValue(base);
}
base = xScale.getPixelForValue(xScale.min);
if (xScale.beginAtZero || ((xScale.min <= 0 && xScale.max >= 0) || (xScale.min >= 0 && xScale.max <= 0))) {
base = xScale.getPixelForValue(0, 0);
} else if (xScale.min < 0 && xScale.max < 0) {
base = xScale.getPixelForValue(xScale.max);
}
return base;
},
getRuler: function () {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var datasetCount = this.getBarCount();
var tickHeight = (function () {
var min = yScale.getPixelForTick(1) - yScale.getPixelForTick(0);
for (var i = 2; i < this.getDataset().data.length; i++) {
min = Math.min(yScale.getPixelForTick(i) - yScale.getPixelForTick(i - 1), min);
}
return min;
}).call(this);
var categoryHeight = tickHeight * yScale.options.categoryPercentage;
var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
var fullBarHeight = categoryHeight / datasetCount;
var barHeight = fullBarHeight * yScale.options.barPercentage;
var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
return {
datasetCount: datasetCount,
tickHeight: tickHeight,
categoryHeight: categoryHeight,
categorySpacing: categorySpacing,
fullBarHeight: fullBarHeight,
barHeight: barHeight,
barSpacing: barSpacing,
};
},
calculateBarHeight: function () {
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var ruler = this.getRuler();
if (yScale.options.stacked) {
return ruler.categoryHeight;
}
return ruler.barHeight;
},
calculateBarY: function (index, datasetIndex) {
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var barIndex = this.getBarIndex(datasetIndex);
var ruler = this.getRuler();
var leftTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
leftTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;
if (yScale.options.stacked) {
return leftTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
}
return leftTick +
(ruler.barHeight / 2) +
ruler.categorySpacing +
(ruler.barHeight * barIndex) +
(ruler.barSpacing / 2) +
(ruler.barSpacing * barIndex);
},
calculateBarX: function (index, datasetIndex) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var value = this.getDataset().data[index];
if (xScale.options.stacked) {
var sumPos = 0,
sumNeg = 0;
for (var i = 0; i < datasetIndex; i++) {
var ds = this.chart.data.datasets[i];
if (Chart.helpers.isDatasetVisible(ds)) {
if (ds.data[index] < 0) {
sumNeg += ds.data[index] || 0;
} else {
sumPos += ds.data[index] || 0;
}
}
}
if (value < 0) {
return xScale.getPixelForValue(sumNeg + value);
} else {
return xScale.getPixelForValue(sumPos + value);
}
return xScale.getPixelForValue(value);
}
return xScale.getPixelForValue(value);
}
});
and then
var config = {
type: 'HorizontalBar',
...
Fiddle - http://jsfiddle.net/0y8mnma1/
score:0
It is a temporary hack but for now you could rotate the entire graph 90 degrees making it horizontal.
Demo
#my-chart {
width: 100%;
transform: rotate(-90deg);
}
.column {
width: 100%;
height: 50px;
}
.column-1 {
background: orange;
}
.column-2 {
background: green;
}
<div id="my-chart">
<div class="column column-1">Column 1</div>
<div class="column column-2">Column 2</div>
</div>
score:0
Am not sure if it will work, but you can try. I am working on Charts.js now and found some limitations and stumbled upon this library that is a custom version of Charts.js
https://github.com/FVANCOP/ChartNew.js
You dont need to change any old format you were using to pull data. Just replace your scripts to use :
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="/pathTo/ChartNew.js"></script>
<script src="/pathTo/shapesInChart.js"></script>
In shapesInChart.js files you will see customized shapes and cases. It has one for HorizontalBar and HorizontalStackedBar
Let me know if it works for you :)
score:0
I edited @potatopeelings original example a bit, so now you can have offsetGridLines set to your liking and working tooltip!
Chart.defaults.HorizontalBar = {
hover: {
mode: "label"
},
tooltips: {
mode: "label",
callbacks: {
title: function(tooltipItems, data) {
label = [];
for (index in tooltipItems) {
if (label.indexOf(tooltipItems[index].yLabel) < 0) label.push(tooltipItems[index].yLabel)
}
return label.join(", ");
},
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ': ' + tooltipItem.xLabel;
}
}
},
scales: {
yAxes: [{
position: 'left',
type: "category",
categoryPercentage: 0.8,
barPercentage: 1,
gridLines: {
offsetGridLines: true
}
}],
xAxes: [{
ticks: {
beginAtZero: true
},
position: 'bottom',
type: "linear",
}],
},
};
Chart.controllers.HorizontalBar = Chart.controllers.bar.extend({
initialize: function(chart, datasetIndex) {
// insert dummy labels for proper vertical positioning
if (!datasetIndex && !chart.config.options.scales.yAxes[0].gridLines.offsetGridLines) {
chart.config.data.labels.unshift('')
chart.config.data.labels.push('')
}
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
this.getDataset().bar = true;
},
updateElement: function updateElement(rectangle, index, reset, numBars) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var xScalePoint;
if (xScale.min < 0 && xScale.max < 0) {
xScalePoint = xScale.getPixelForValue(xScale.max);
} else if (xScale.min > 0 && xScale.max > 0) {
xScalePoint = xScale.getPixelForValue(xScale.min);
} else {
xScalePoint = xScale.getPixelForValue(0);
}
Chart.helpers.extend(rectangle, {
_chart: this.chart.chart,
_xScale: xScale,
_yScale: yScale,
_datasetIndex: this.index,
_index: index,
_model: {
x: reset ? xScalePoint : this.calculateBarX(index, this.index),
y: this.calculateBarY(index, this.index),
label: this.chart.data.labels[index],
datasetLabel: this.getDataset().label,
base: this.calculateBarBase(this.index, index),
height: this.calculateBarHeight(numBars),
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : Chart.helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth),
},
// override the inRange function because the one in the library needs width (we have only height)
inRange: function(mouseX, mouseY) {
var vm = this._view;
var inRange = false;
if (vm) {
if (vm.x < vm.base) {
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
} else {
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
}
}
return inRange;
}
});
rectangle.pivot();
// the animation progresses _view values from their current value to the _model value
rectangle._view.x = rectangle._model.base;
},
calculateBarBase: function(datasetIndex, index) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var base = 0;
if (xScale.options.stacked) {
var value = this.chart.data.datasets[datasetIndex].data[index];
if (value < 0) {
for (var i = 0; i < datasetIndex; i++) {
var negDS = this.chart.data.datasets[i];
if (Chart.helpers.isDatasetVisible(negDS) && negDS.xAxisID === xScale.id) {
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
}
}
} else {
for (var j = 0; j < datasetIndex; j++) {
var posDS = this.chart.data.datasets[j];
if (Chart.helpers.isDatasetVisible(posDS) && posDS.xAxisID === xScale.id) {
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
}
}
}
return xScale.getPixelForValue(base);
}
base = xScale.getPixelForValue(xScale.min);
if (xScale.beginAtZero || ((xScale.min <= 0 && xScale.max >= 0) || (xScale.min >= 0 && xScale.max <= 0))) {
base = xScale.getPixelForValue(0, 0);
} else if (xScale.min < 0 && xScale.max < 0) {
base = xScale.getPixelForValue(xScale.max);
}
return base;
},
draw: function(ease) {
var easingDecimal = ease || 1;
var ctx = this.chart.chart.ctx;
ctx.save();
Chart.helpers.each(this.getDataset().metaData, function(rectangle, index) {
ctx.fillStyle = rectangle._view.backgroundColor;
ctx.fillRect(rectangle._view.base, rectangle._view.y - rectangle._view.height / 2, rectangle._view.x - rectangle._view.base, rectangle._view.height);
ctx.strokeStyle = rectangle._view.borderColor;
ctx.strokeWidth = rectangle._view.borderWidth;
ctx.strokeRect(rectangle._view.base, rectangle._view.y - rectangle._view.height / 2, rectangle._view.x - rectangle._view.base, rectangle._view.height);
rectangle.transition(easingDecimal).draw();
}, this);
ctx.restore();
},
getRuler: function() {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var datasetCount = this.getBarCount();
var tickHeight = (function() {
var min = yScale.getPixelForTick(1) - yScale.getPixelForTick(0);
for (var i = 2; i < this.getDataset().data.length; i++) {
min = Math.min(yScale.getPixelForTick(i) - yScale.getPixelForTick(i - 1), min);
}
return min;
}).call(this);
var categoryHeight = tickHeight * yScale.options.categoryPercentage;
var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
var fullBarHeight = categoryHeight / datasetCount;
var barHeight = fullBarHeight * yScale.options.barPercentage;
var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
return {
datasetCount: datasetCount,
tickHeight: tickHeight,
categoryHeight: categoryHeight,
categorySpacing: categorySpacing,
fullBarHeight: fullBarHeight,
barHeight: barHeight,
barSpacing: barSpacing,
};
},
calculateBarHeight: function() {
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var ruler = this.getRuler();
console.debug(yScale.options.stacked);
if (yScale.options.stacked) {
return ruler.categoryHeight;
}
return ruler.barHeight;
},
calculateBarY: function(index, datasetIndex) {
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var barIndex = this.getBarIndex(datasetIndex);
var ruler = this.getRuler();
var leftTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
leftTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;
leftTick = (!yScale.options.gridLines.offsetGridLines) ? leftTick + (ruler.tickHeight / 2) : leftTick;
if (yScale.options.stacked) {
return leftTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
}
return leftTick + 1 +
(ruler.barHeight / 2) +
ruler.categorySpacing +
(ruler.barHeight * barIndex) +
(ruler.barSpacing / 2) +
(ruler.barSpacing * barIndex);
},
calculateBarX: function(index, datasetIndex) {
var xScale = this.getScaleForId(this.getDataset().xAxisID);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
var value = this.getDataset().data[index];
if (xScale.options.stacked) {
var sumPos = 0,
sumNeg = 0;
for (var i = 0; i < datasetIndex; i++) {
var ds = this.chart.data.datasets[i];
if (Chart.helpers.isDatasetVisible(ds)) {
if (ds.data[index] < 0) {
sumNeg += ds.data[index] || 0;
} else {
sumPos += ds.data[index] || 0;
}
}
}
if (value < 0) {
return xScale.getPixelForValue(sumNeg + value);
} else {
return xScale.getPixelForValue(sumPos + value);
}
return xScale.getPixelForValue(value);
}
});
cheers c_bb
Source: stackoverflow.com
Related Query
- Chart.js v2 is there a way to draw bar chart horizontally?
- Is there any way to remove extra space and Horizontal line from Bar chart of Chart.js?
- Is there any way to change the font size of labels in bar chart in Chart.js v3?
- How do I draw a vertical line on a horizontal bar chart with ChartJS?
- Chart.js - Draw bar chart with multiple labels
- How to draw Horizontal line on Bar Chart Chartjs
- Chart Js V2 draw Horizontal Bar(Average) Over Vertical Bar
- Draw a horizontal bar chart from right to left
- Is there any way to use 2 different color for the same bar in a chart?
- Chart JS : Getting issue with draw bar chart
- Is there any way to get Chiselled Effect in chart js?
- How to draw baseline for bar chart in chart.js
- chart.js pie chart background colors: is there any way to generate them randomly?
- How to draw multiple color bar in a bar chart using chart.js
- Is there a convenient way to print values to a JS chart from a CSV file without converting it?
- Chart.js - draw horizontal line in Bar Chart (type bar)
- How to draw border all the way around bar element
- Is there any way to display float bar in chart.js?
- Draw points and lines inside a bar in bar chart
- Is there a way to give a pie chart in chart.js a different color outer border than the border color between segments?
- Is there a way to draw floating rectangle using chart.js
- Is there a way to display a chart label that has no data behind it in Chart.js
- chart.js Is there way to color line chart ticks depending on value
- How to draw multiple color bars in a bar chart along a Horizontal Line using chart.js
- Chart JS - Is there a way to connect two datasets in a line chart?
- How we can draw a circle in bar chart
- (Chart.js) Is there a way to compare one chart with another so as not to have this inconsistent effect of small values being as big as big values?
- Is there a way to style multiple borders on Doughnut chart with Chart.js library?
- Is there a more optimized way to implement the change function of chart js upon changing the dropdowns?
- Chart.js Draw a Stacked Bar Chart with Limit Line
More Query from same tag
- Using Object.assign to merge objects
- Remove empty spaces created by null values in Chart.js
- Charts.js - onComplete javascript function coming from JSON
- Polar Area in Chart JS Rotates When Adding Labels
- How do I draw horizontal bars with a label using either ChartJS or D3?
- chart.js legend not working for pie chart
- multiple charts js in page but with same tooltips (about last chart)
- Want to show the dataset labels
- Chart.js "display:none" Issue
- Chart isn't updating with Response data (Chart.js 3.2.1, ng2-charts 3.0.0-beta.9)
- Display data label (legend) in line-chart using chartjs
- Chart.js HTML custom legend issues with doughnut chart
- Why Primefaces donutChart is not working?
- Django Chart.js ajax javascript "string data parsing error"
- How to show tooltip only when data available in chart js?
- How to zoom charts in chart.js using angular 7
- chart.js not allowing y axis steps with logarithmic scale
- Cannot create property 'datasets' on string
- How to hide radar chart index labels (chart.js)
- ChartJS horizontal chart display legend on each bar
- chartjs with local dates
- Chart.js move start position of chart from axis
- Multiple axis line chart with Chart.js and JSON data from Google Sheet
- Tooltip vertically off with overlapping data, in ChartJS
- how to change color of dots in graph using chart.js
- ChartJs: Loading fresh data to Chart
- Chart.js: how to listen to hover/click events outside of plot area?
- Chart.js load new data from saved JSON object
- Import data from Excel and use in Chart.js
- DiscordAPIError: Invalid Form Body embed.image.url: Scheme "[object response]" is not supported. Scheme must be one of ('http', 'https')