c3js bar chart, align data to x tick start position (not centered) - javascript

If you take a normal bar chart from c3js, the bars will be centered at the x-tick position. I have a chart which goes hourly, so any timespan between 00-24 (usually like 8-16). If I have a line-chart or scatter plot it will align it self exactly on the x-tick nicely, but not as a step-chart or a bar chart.
var chart = c3.generate({
data: {
x: 'x',
columns: [
['x', 8, 9, 10, 11, 12, 13, 14, 15, 16],
['data1', 1, 1, 0, 1, 0, 0, 1, 1, 1],
],
type: "bar"
},
axis: {
x: {
type: "category",
categories: [],
}
}
});
See this fiddle: https://jsfiddle.net/jvcarphe/1/
I've been trying with all sorts of culling / tick values / time series etc. but I can't for the love of god figure out how to do it. If the type in the fiddle is changed to "line" it does exactly what I want, beside it's not a bar.

I've had to do this before and there doesn't seem to be a simple setting that does it, but a bit of d3 manipulation works. I came to the conclusion it's easier to move the ticks than the bars:
If you know the width of your bar, you can set a css rule to offset the ticks, just change the -10px to whatever is necessary -->
.c3-axis-x .tick line, .c3-axis-x .tick text {
transform: translate(-10px,0);
}
(can't just apply the rule to .tick as c3 overrides its transform style)
If you don't know the width then you need to find it out by querying one of the bars and applying the same style rule dynamically in c3's onrendered callback:
onrendered: function () {
var thisChart = d3.select(this.config.bindto);
var barWidth = thisChart.select(".c3-bar-0").node().getBoundingClientRect().width / 2;
thisChart.selectAll(".c3-axis-x .tick line,.c3-axis-x .tick text").style("transform", "translate(-"+barWidth+"px,0)");
}
Fiddle edited as newer version of c3 didn't work in the fiddle:
https://jsfiddle.net/15w50f06/4/

Related

plotly js colorscale for errorbars

I want to plot the scattered data with a colorscale and the errorbars should have the same colorscale.
I found answers for plotly R (How do you make plotly error bars follow a colorscale?), but I can't translate it to js. Also using the name attribute for this seems strange to me.
Here is a minimal example (https://jsfiddle.net/ztqoemkd/1)
var trace1 = {
type: 'scatter',
mode: 'markers',
y: [2, 1, 3],
marker: {
size: 20,
color: [1, 2, 3],
showscale: true
},
error_y: {
type:'data',
array: [0.5, 0.7, 0.5],
color: [1, 2, 3]
}
}
Plotly.newPlot('myDiv', [trace1])
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>
I still don't know, if can be done self consistently with plotly itself.
At least, I could now develop this work around with d3:
// get colors from data points
rgbs = Plotly.d3.selectAll('.points .point').data().map(d => d.mcc)
// apply colors to errorbars
Plotly.d3.selectAll('.yerror').style('stroke', (d,i) => rgbs[i])
Here is the full demo:
https://jsfiddle.net/vor6e9wj
and the output is
Note 1: After zooming, the errorbars are again black.
Note 2: It does not work for scattergl.
Edit 1: To keep the colors while zooming, the work around can be attached to plotly_relayout (see https://jsfiddle.net/9s64y5cv).

How to add padding in a bar chart between the outer bars and the left/right sides in Chart.js?

When creating a bar chart in Chart.js all bars take up the whole horizontal space. How can I add some padding to the most left and most right bar to achieve what you see in the image below:
Alternativly this may be achieved if the bars are aligned in the center and using a max-width in percentage on the bars itself, so that they will never fill up the whole space. But I can't find any options for that either.
Currently I'm adding two 0 values with blank labels on each side, which works, but it's just a workaround:
var data = {
labels: ['', '', 1, 2, 3, '', ''],
datasets: [{
data: [0, 0, 36500, 59000, 65000, 0, 0],
backgroundColor: [
null,null,
'blue','blue','blue',
null,null
],
}]
};
I'm using Chart.js 2.3.

Data graph labels cut off on c3.js chart

I'm graphing some lines on a c3.js line chart, but the data label of the leftmost point is being cut off:
I've tried adding padding to the chart, but this just adds padding to the overall chart. What I need is some way to add some sort of padding to just the bar graph ticks.
Something that I've considered:
I've considered using the "transform" property:
.c3-texts .c3-text text {
transform: translate(10px, 0);
}
But moving the position of all the data labels to the right would end up causing the data labels on the right-hand side of the graph to get cut off.
Here's a simple example of labels getting cut off:
fiddle
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250]
],
labels: {
format: function(x){
return "Test Label"
}
}
}
});
Any help would be appreciated. Thanks!
#ksav pointed me in the right direction. I remember trying this before, but foolishly, I didn't think of putting decimal numbers. I had tried putting in the value 1, and it gave way too much padding, but doing the following worked perfectly:
axis: {
x: {
padding: {
left: 0,
right: 0,
}
}
}

Customizing Chart.js troubleshoot

Have some trouble with Chart.js
1) is it possible to move bottom labels on top of the chart?
2) is it possible to hide left labels with first grey line?
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
Here is my chart http://jsfiddle.net/JohnnyJuarez/ojc09hv4/:
<canvas id="weeksChart" width="651" height="335"></canvas>
var dayTemperatureArray = [-5, 14, 15, 15, 17, 18, 19, 21, 22, 25, 24, 20, 19, 16];
var nightTemperatureArray = [-10, 4, 5, 6, 8, 11, 12, 15, 17, 15, 13, 12, 11, 9];
var dataWeeks = {
labels: ["16.02", "17.02", "18.02", "19.02", "20.02", "21.02", "22.02", "23.02", "24.02", "25.02", "26.02", "27.02", "28.02", "01.03"],
datasets: [
{
label: "Days temperature chart",
fillColor: "transparent",
strokeColor: "rgba(244, 6, 6, 1)",
data: dayTemperatureArray
},
{
label: "Nights temperature chart",
strokeColor: "#3f6bf5",
data: nightTemperatureArray
}
]
};
var ctx = document.getElementById("weeksChart").getContext("2d");
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
responsive: true,
pointDot: true,
datasetStrokeWidth: 0.5,
scaleSteps: 2,
scaleLabel: "<%=value + '°'%>",
tooltipTemplate: "<%= value %>",
showTooltips: true
});
Thanx a lot in advance!
p.s. please avoid jquery, if it's possible :-)
Let's start with the easiest one first
2) is it possible to hide left labels with first grey line?
I assume you meant the y axis labels. You can set the scaleShowLabels option to false in the chart options to hide the y axis labels
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleShowLabels: false,
...
1) is it possible to move bottom labels on top of the chart?
I assume you mean the x axis labels. Chart.js doesn't have a direct option to do this. However you can hide the actual x axis labels and draw the x axis labels at the top of the chart by yourself.
Again, Chart.js doesn't have an option to hide x axis labels, but luckily there is an option to control the scale font color. Just set it to transparent and your original x axis labels are now hidden!
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleFontColor: "transparent",
...
Now the drawing of the x axis labels at the top of the chart. To save us the trouble of extending the chart, we can add a post animation event handler and do this in that, like so
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
onAnimationComplete: function () {
animationComplete.apply(this)
}
...
with
var animationComplete = function () {
var self = this;
Chart.helpers.each(self.datasets[0].points, function (point, index) {
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
We just loop through all points in one of the dataset and add the labels (scale.startPoint is the top edge of the chart area)
Note - why do we set the font, alignment, etc. every iteration? That's for when we add the tooltips.
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
The first step would be to actually show the tooltips. This is fairly simple, though a bit tedious. We loop through all the x axis point, build the label (by going through each dataset) and then construct a tooltip (fortunately, we can use Chart.MultiTooltip function for this.
We add it into the same loop we used to construct the new x axis labels. Since we need to color our tooltips, we need to get and store the set of colors in an array (which we pass on to the MultiTooltip function - we need to do this only once, so we take it out of the loop.
The modified animationComplete function is now this
var animationComplete = function () {
var self = this;
var tooltipColors = []
Chart.helpers.each(self.datasets, function (dataset) {
tooltipColors.push({
fill: dataset.strokeColor,
stroke: dataset.strokeColor
})
});
Chart.helpers.each(self.datasets[0].points, function (point, index) {
var labels = []
var total = 0;
Chart.helpers.each(self.datasets, function (dataset) {
labels.push(dataset.points[index].value)
total += Number(dataset.points[index].y);
});
new Chart.MultiTooltip({
x: point.x,
y: total / 2,
xPadding: self.options.tooltipXPadding,
yPadding: self.options.tooltipYPadding,
xOffset: self.options.tooltipXOffset,
fillColor: self.options.tooltipFillColor,
textColor: self.options.tooltipFontColor,
fontFamily: self.options.tooltipFontFamily,
fontStyle: self.options.tooltipFontStyle,
fontSize: self.options.tooltipFontSize,
titleTextColor: self.options.tooltipTitleFontColor,
titleFontFamily: self.options.tooltipTitleFontFamily,
titleFontStyle: self.options.tooltipTitleFontStyle,
titleFontSize: self.options.tooltipTitleFontSize,
cornerRadius: self.options.tooltipCornerRadius,
labels: labels,
legendColors: tooltipColors,
legendColorBackground: self.options.multiTooltipKeyBackground,
title: point.label,
chart: self.chart,
ctx: self.chart.ctx,
custom: self.options.customTooltips
}).draw()
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
It looks complex, but all we are doing is passing a options that we copy from the chart instance options to the MultiTooltip function.
The tooltips all show up when the animation is complete. HOWEVER, once you move your mouse over the chart they all up and disappear! That's because the chart instance listens for multiple events to decide whether to start checking if tooltips should be shown - one of these is mousemove (and that causes it to redraw the chart, wiping out all our hard drawn tooltips and, if we are lucky, it draws a tooltip based on the point our mouse is hovering over)
This is a configurable option. So, all we have to do is remove all such events.
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
tooltipEvents: []
...
Working fiddle - http://jsfiddle.net/fuodxsfv/
Unless your chart is wide enough, you will have tooltips (mostly the middle 2 ones) overlap (of course you could incorporate logic into the above loop to handle that), but anyhoo, those were actually meant to be tooltips!

C3.js Y Axis Range (Max/Min) Doesn't Work for a Bar Chart

I am trying to put together a bar chart in C3.
http://jsfiddle.net/michaelkuzmin/Lcxe0frw/9/
var chart = c3.generate({
data: {
columns: [
['% Women CS', 0.036, 0.095, 0.105, 0.182, 0.121],
['% Women Math', 0.182, 0.077, 0.182, 0.026, 0.097],
['% Women Comp Eng /EE', 0.039, 0.074, 0.032, 0.095, 0.087]
],
type: 'bar',
labels: true
},
axis : {
y : {
tick: {
max: 0.50,
min: 0,
// padding: {top: 0, bottom: 0}
}
},
x: {
type: 'category',
categories: ['Carleton', 'Alberta', 'Sherbrooke', 'McGill', 'Laval']
}
}
});
1) When I enable value labels the Y axis immediately breaks by setting the max range to 14
2) When I try to set it manually it ignores the Y: max min parameters.
What am I missing?
P/S Somebody posted a very similar question here c3.js y axis min/max not working
but the solution they posted does not work for me. The solution was to use padding = 0. You can uncomment it in the fiddle and see that it makes no difference.
The documentation on c3.js is pretty poor, but it seems that the max and min don't belong in the y.tick object, but directly in the y. Moving them, and then applying the padding to the y as well, seems to resolve the issue. See updated fiddle here.

Categories