14๐
โ
New modes can be defined by adding functions to the Chart.Tooltip.positioners map (DOC). This function returns the x and y position for the tooltip.
You can add a custom one to adjust the x at an offset.
One way to do this would be to be:
//register custome positioner
Chart.Tooltip.positioners.custom = function(elements, position) {
if (!elements.length) {
return false;
}
var offset = 0;
//adjust the offset left or right depending on the event position
if (elements[0]._chart.width / 2 > position.x) {
offset = 20;
} else {
offset = -20;
}
return {
x: position.x + offset,
y: position.y
}
}
Fiddle example that I created
I hope it helps.
7๐
I had the same issue and I didnโt find a good solution, so I had to dot it myself.
Actually, itโs simple than I thought, wish it helps someone.
Demo: https://codepen.io/themustafaomar/pen/wvWZrod
const labels = ["1 April","2 April","3 April","4 April","5 April","6 April","7 April","8 April","9 April","10 April","11 April","12 April","13 April","14 April","15 April","16 April","17 April","18 April","19 April","20 April","21 April","22 April","23 April","24 April","25 April","26 April","27 April","28 April","29 April","30 April","31 April"]
const data = [ 95, 57, 72, 54, 73, 53, 98, 75, 52, 93, 50, 65, 99, 67, 77, 61, 74, 65, 86, 92, 64, 89, 82, 62, 64, 89, 59, 75, 56, 63 ];
function customTooltips(tooltipModel) {
// Tooltip Element
var tooltipEl = document.getElementById("chartjs-tooltip");
const yAlign = tooltipModel.yAlign;
const xAlign = tooltipModel.xAlign;
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement("div");
tooltipEl.id = "chartjs-tooltip";
tooltipEl.innerHTML = "<table></table>";
document.body.appendChild(tooltipEl);
}
// Hide if no tooltip
if (tooltipModel.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
tooltipEl.classList.remove("top", "bottom", "center", "left", "right");
if (tooltipModel.yAlign || tooltipModel.xAlign) {
tooltipEl.classList.add(tooltipModel.yAlign);
tooltipEl.classList.add(tooltipModel.xAlign);
}
// Set Text
if (tooltipModel.body) {
var titleLines = tooltipModel.title || [];
var bodyLines = tooltipModel.body.map((bodyItem) => {
return bodyItem.lines;
});
var innerHtml = "<thead>";
titleLines.forEach(function (title) {
innerHtml += '<tr><th><div class="mb-1">' + title + "</div></th></tr>";
});
innerHtml += "</thead><tbody>";
bodyLines.forEach((body, i) => {
var colors = tooltipModel.labelColors[i];
// var style = 'background-color:' + colors.borderColor
var style =
"background-color:" + this._chart.data.datasets[i].borderColor;
var value = tooltipModel.dataPoints[i].value;
var label = this._chart.data.datasets[i].label;
style += "; border-color:" + colors.borderColor;
style += "; border-color:" + this._chart.data.datasets[i].borderColor;
style += "; border-width: 2px";
var span =
'<span class="chartjs-tooltip-key" style="' + style + '"></span>';
innerHtml += `<tr><td> ${span} $${value}K </td></tr>`;
});
innerHtml += "</tbody>";
var tableRoot = tooltipEl.querySelector("table");
tableRoot.innerHTML = innerHtml;
}
// Tooltip height and width
const { height, width } = tooltipEl.getBoundingClientRect();
// Chart canvas positions
const positionY = this._chart.canvas.offsetTop;
const positionX = this._chart.canvas.offsetLeft;
// Carets
const caretY = tooltipModel.caretY;
const caretX = tooltipModel.caretX;
// Final coordinates
let top = positionY + caretY - height;
let left = positionX + caretX - width / 2;
let space = 8; // This for making space between the caret and the element.
// yAlign could be: `top`, `bottom`, `center`
if (yAlign === "top") {
top += height + space;
} else if (yAlign === "center") {
top += height / 2;
} else if (yAlign === "bottom") {
top -= space;
}
// xAlign could be: `left`, `center`, `right`
if (xAlign === "left") {
left = left + width / 2 - tooltipModel.xPadding - space / 2;
if (yAlign === "center") {
left = left + space * 2;
}
} else if (xAlign === "right") {
left -= width / 2;
if (yAlign === "center") {
left = left - space;
} else {
left += space;
}
}
// Display, position, and set styles for font
tooltipEl.style.opacity = 1;
// Left and right
tooltipEl.style.top = `${top}px`;
tooltipEl.style.left = `${left}px`;
// Font
tooltipEl.style.fontFamily = tooltipModel._bodyFontFamily;
tooltipEl.style.fontSize = tooltipModel.bodyFontSize + "px";
tooltipEl.style.fontStyle = tooltipModel._bodyFontStyle;
// Paddings
tooltipEl.style.padding =
tooltipModel.yPadding + "px " + tooltipModel.xPadding + "px";
}
// Chart
new Chart("chart", {
type: "line",
data: {
labels,
datasets: [
{
label: "Custom tooltip demo",
borderColor: "#f66",
backgroundColor: "transparent",
lineTension: 0,
borderWidth: 1.5,
pointRadius: 2,
data
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: { display: false },
scales: {
// YAxes
yAxes: [{ display: false }],
// XAxes
xAxes: [
{
display: false,
gridLines: { display: false },
ticks: {
padding: 20,
autoSkipPadding: 30,
maxRotation: 0
}
}
]
},
tooltips: {
enabled: false,
intersect: false,
mode: "index",
position: "average",
custom: customTooltips
}
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.chartjs-wrapper {
height: 90px;
width: 300px;
margin: 25px auto 0;
border: 1px solid #e6e6e6;
}
#chartjs-tooltip {
opacity: 1;
position: absolute;
color: #fff;
background-color: #000;
border-radius: 6px;
transition: all 0.25s ease-in-out;
pointer-events: none;
}
#chartjs-tooltip:after {
content: "";
display: block;
position: absolute;
margin: auto;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
}
/* Top center */
#chartjs-tooltip.top.center:after {
border-bottom-color: #000;
top: -11px;
left: 0;
right: 0;
}
/* Top left */
#chartjs-tooltip.top.left:after {
border-bottom-color: #000;
left: 5px;
top: -11px;
}
/* Top right */
#chartjs-tooltip.top.right:after {
border-bottom-color: #000;
right: 5px;
top: -11px;
}
/* Bottom center */
#chartjs-tooltip.bottom.center:after {
border-top-color: #000;
bottom: -11px;
right: 0;
left: 0;
}
/* Bottom left */
#chartjs-tooltip.bottom.left:after {
border-top-color: #000;
bottom: -11px;
}
/* Bottom right */
#chartjs-tooltip.bottom.right:after {
border-top-color: #000;
bottom: -11px;
right: 5px;
}
/* Center left */
#chartjs-tooltip.center.left:after {
border-right-color: #000;
margin: auto;
left: -11px;
bottom: 0;
top: 0;
}
/* Center right */
#chartjs-tooltip.center.right:after {
border-left-color: #000;
margin: auto;
right: -11px;
bottom: 0;
top: 0;
}
.chartjs-tooltip-key {
display: inline-block;
border-radius: 50%;
width: 10px;
height: 10px;
margin-right: 7px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<div class="chartjs-wrapper">
<canvas id="chart"></canvas>
</div>
3๐
I did this:
Subtract the pixels by way of centering it or putting it in the position.
tooltipEl.style.left = canvas.offsetLeft + tooltip.caretX - 55 + 'px';
0๐
U use this in addition to externalTooltipHandler from chartJs
This will modify position only for latest tooltip
var currentTooltip = tooltip.dataPoints[0].dataIndex;
var keys = Object.keys(tooltip.dataPoints[0].dataset.data);
var latestTooltip = keys[keys.length - 1];
if (currentTooltip == latestTooltip) {
tooltipEl.style.left = chart.canvas.offsetLeft + tooltip.caretX - 70 + "px";
} else {
tooltipEl.style.left = positionX + tooltip.caretX + "px";
}
Source:stackexchange.com