I am wanting to move the tooltip downwards a few pixels instead of always at the top of each stack (on stacked bar chart).
I found this in the docs about positioners, but I cannot understand the structure of code and where it should actually go.
Chart.Tooltip.positioners.custom = function(elements, eventPosition) {
var tooltip = this;
return {
x: 0,
y: -50
};
}
For reference, you can see where I've tried to place it here ( not much wonder why its not working )
Config seems to have a position and yPadding, neither of which seem to have effect I want when I put them in the tooltips options:
tooltips: {
yAlign: 'top',
position: 'nearest',
yPadding: 50
}
yPadding distorts the tooltip, I'm not sure why but it muddles up the caret and box.
Related
What I have
I've created 2 graphs like shown in the first image below. I need these 2 graphs to be perfectly aligned on the 0 axis (which is shown in the section below).
Wanted result
In the image below, the graphs are perfectly aligned and should therefore contain 2 different datasets. One should be placed on the left grid and the other one on the right grid.
The options I thought of
I have not seen a way to implement this in ChartJS. Therefore, I thought of some possible solutions that could solve this issue in a different way.
Because both datasets don't have negative values, I could convert the left dataset to negative values (on the x-axis). The downside is that the range would be incorrect. Also, this would give issues with the popup message if you hover your mouse on a value.
Maybe, two canvas objects can be combined that could result in the wanted result
Question
Is there a way to achieve the wanted result within ChartJS? Or can I perform some wizardry to combine two charts nicely into one? Or should I move to the D3.js library for this particular graph?
I did not find a way to "nicely" implement this. I've changed the source code of the ChartJS library to implement this.
This method uses 2 different graphs that render in 2 different canvas objects. These canvas objects are placed side-by-side to let it look like one graph.
This is my result (The code in here is not exactly like the graph in the picture because I changed it to my specific needs).
I've added a custom variable in the options.layout category named sidePadding.
The code of creating the graph:
new Chart(document.getElementById(this.element), {
type: 'scatter',
data: {
datasets: [{
borderColor: this.lineColor,
borderWidth: 1,
pointBackgroundColor: '#000',
pointBorderColor: '#000',
pointRadius: 0,
fill: false,
tension: 0,
showLine: true,
data: [],
}],
},
options: {
aspectRatio: 0.3,
maintainAspectRatio: false,
responsive: true,
layout: {
sidePadding: {
left: 3,
right: -3,
}
}
}
});
The padding on the sides is by default 3 so it does not touch the border of the canvas. I wanted it to touch the border of the canvas, and therefore set it to -3.
Two different graphs need to be created, one for the left side and one for the right side.
The left graph should have the sidePadding.right set to -3. The right graph should have the sidePadding.left set to -3.
Changes in the ChartJS library
I've worked with ChartJS version v2.9.3. This method will possibly not work anymore in a new version.
I've changed the following in the Chart.js file:
Replace (line number around 11800):
// Adjust padding taking into account changes in offsets
// and add 3 px to move away from canvas edges
me.paddingLeft = Math.max((paddingLeft - offsetLeft) * me.width / (me.width - offsetLeft), 0) + 3;
me.paddingRight = Math.max((paddingRight - offsetRight) * me.width / (me.width - offsetRight), 0) + 3;
to:
// Adjust padding taking into account changes in offsets
// and add 3 px to move away from canvas edges
var layoutOptions = chart.options.layout || {};
var sidePadding = helpers$1.options.toPadding(layoutOptions.sidePadding);
me.paddingLeft = Math.max((paddingLeft - offsetLeft) * me.width / (me.width - offsetLeft), 0) + sidePadding.left;
me.paddingRight = Math.max((paddingRight - offsetRight) * me.width / (me.width - offsetRight), 0) + sidePadding.right;
Also you must add the sidePadding.left and sidePadding.right parameter to ChartJS.
This can be done by changing (line number around 7180):
core_defaults._set('global', {
layout: {
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
// Custom added parameter
sidePadding: {
left: 3,
right: 3,
}
}
});
to:
core_defaults._set('global', {
layout: {
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
// Custom added parameter
sidePadding: {
left: 3,
right: 3,
}
}
});
Note
This is probably not the best way to achieve this. Changing the ChartJS library is bad-practice and updating the library could revert these changes.
If someone has a better way to achieve this, please post your methods or comment below.
I am trying to add multiple lines in the tooltip for my horizontal stacked bar chart but the last couple lines are getting cut off by the end of the chart canvas. Is it possible to make the tooltip extend over the end of the chart canvas?
tooltips: {
mode: 'nearest',
intersect: true,
callbacks: {
footer: function() {
var withBreaks = "Hello World. \n My name is Jennifer. \n What is your name?"
return withBreaks;
},
}
},
Either you can add bottom padding to your canvas
options: {
layout: {
padding: {
bottom: 25 //set that fits the best
}
},
}
Another option is to set the yAlign of tooltip to center, so the tooltip won't occupy the bottom space of the canvas.
options: {
tooltips: {
yAlign: 'center'
}
}
Please have a look at this issue, especially https://github.com/chartjs/Chart.js/issues/622#issuecomment-72480781 comment.
A similar problem was faced here too.
In Highcharts, I know you can put your tooltip in a fixed position using:
tooltip: {
positioner: function () {
return { x: 50, y: 50 };
},
},
But how would I center it in the same way that margin: 0 auto would center it? I am trying to get the tooltip text to stay in the middle of a donut chart. The solution is probably something obvious but I have yet to figure out what it is. Thanks in advance!
You can make use of chart plotHeight and plotWidth to get access to current chart height and width and adjust the tooltip x and y accordingly as below:
positioner:function(){
return { x: chart.plotWidth/2, y: chart.plotHeight/2 };
}
A working demo here: https://angular-raebwk.stackblitz.io
How to keep the chart from cropping on resize, but instead just change its viewport?
I find it a a bit hard to explain, so please let me know if more explanation is needed.
The chart on the first screenshot look nice, they have a 'normal spacing between them and the bars are not cropped. This one has a 1000px width.
Chart box wide
On the second screenshot, the chart is only 300px wide, and the candlesticks become 'cropped'..
Chart box cropped
Instead I would like to only change the viewport, so that the bars are never cropped and are always te same size.. Only the date-range (Viewport) changes.. You see more bars on a wider chart, but it doesn't meen the bars itself should grow or shrink.
I tried it with simple algoritme, but its very prone to error.
let parentW = this._elementRef.nativeElement.parentNode.clientWidth,
data = this.chart.xAxis[0].series[0].data,
barW = 10,
barsToShow = Math.ceil(parentW / barW),
firstBar = (data[data.length - barsToShow] || data[0]),
lastBar = data[data.length - 1];
this.chart.xAxis[0].setExtremes(firstBar.x, lastBar.x, redraw);
I couldn't find any setting in the Highcharts doc and google didn't help much either. Many thanks
Desired behaviour can be achieved with the changing data grouping groupPixelWidth property.
When the chart has smaller width than, e.g. 300px, groupPixelWdith can be set to a higher value.
responsive: {
rules: [{
chartOptions: {
plotOptions: {
series: {
dataGrouping: {
groupPixelWidth: 30
}
}
}
},
condition: {
maxWidth: 300
}
}]
}
example: http://jsfiddle.net/b894z8ug/1/
I have a highchart graph with tooltips. This is how I want to render tooltips every time.
When the tootlip doesn't fit the svg container, highcharts swaps the position of tooltip like this.
I know how to fix this but when I do this.
positioner: function(boxWidth, boxHeight, point) {
return {
x: point.plotX,
y: point.plotY - boxHeight
};
},
Tooltip is correctly always on top, but overflows to the right(image_1). I would like to have the tooltip always on top + fit the container from the sides. (image_2)
Is there any easy way to achieve this?
Thanks (http://jsfiddle.net/4xomw3aj/)
Ok I just found out how to 'not swap'. In Tooltip.getPosition()
firstDimension = function (dim, outerSize, innerSize, point) {
ret[dim] = point - distance - innerSize;
},