无法找到一种方法将工具提示放在这样的栏中心(是的,我知道它并不完全位于此屏幕截图的中心位置,但仍然存在):
如果我使用custom
工具提示选项,我只能在条形图上方获得插入符号的GET /../tn/d9dd6c39d71276487ae798d976f8f629_tn.jpg
和x
个位置。但无法获得酒吧的高度/宽度。
这是我传递给Chart构造函数的选项对象的一部分:
y
答案 0 :(得分:1)
您可以使用datasets
中的值来锻炼悬停的项目的相对高度,并相应地调整CSS。
以下是靠近中心,但不是确切的中心。如果你想要准确,我的计算需要纠正。
自定义工具提示功能包括以下内容:
// find relative proportion
var dataIndex = tooltip.dataPoints[0].index;
var datasetIndex = tooltip.dataPoints[0].datasetIndex;
var totalHeight = 0;
var thisHeight = this._chart.config.data.datasets[datasetIndex].data[dataIndex];
for (var i = 0; i <= datasetIndex; i++)
{
totalHeight += this._chart.config.data.datasets[i].data[dataIndex];
}
var positionY = this._chart.canvas.offsetTop;
var positionX = this._chart.canvas.offsetLeft;
var chartHeight = this._chart.canvas.scrollHeight;
var tooltipHalfHeight = tooltip.height / 2;
// Display, position, and set styles for font
tooltipEl.style.left = positionX + tooltip.caretX + 'px';
tooltipEl.style.top = tooltip.caretY + ((chartHeight - tooltip.caretY - positionY) * (thisHeight / totalHeight / 2)) - tooltipHalfHeight + 'px';
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js"></script>
<script src="script.js"></script>
<style>
canvas{
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
#chartjs-tooltip {
opacity: 1;
position: absolute;
background: rgba(0, 0, 0, .7);
color: white;
border-radius: 3px;
-webkit-transition: all .1s ease;
transition: all .1s ease;
pointer-events: none;
/*-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);*/
}
.chartjs-tooltip-key {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="chartjs-tooltip">
<table></table>
</div>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var customTooltips = function(tooltip) {
// Tooltip Element
var tooltipEl = document.getElementById('chartjs-tooltip');
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'chartjs-tooltip';
tooltipEl.innerHTML = "<table></table>"
this._chart.canvas.parentNode.appendChild(tooltipEl);
}
// Hide if no tooltip
if (tooltip.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
tooltipEl.classList.remove('above', 'below', 'no-transform');
if (tooltip.yAlign) {
tooltipEl.classList.add(tooltip.yAlign);
} else {
tooltipEl.classList.add('no-transform');
}
function getBody(bodyItem) {
return bodyItem.lines;
}
// Set Text
if (tooltip.body) {
var titleLines = tooltip.title || [];
var bodyLines = tooltip.body.map(getBody);
var innerHtml = '<thead>';
titleLines.forEach(function(title) {
innerHtml += '<tr><th>' + title + '</th></tr>';
});
innerHtml += '</thead><tbody>';
bodyLines.forEach(function(body, i) {
var colors = tooltip.labelColors[i];
var style = 'background:' + colors.backgroundColor;
style += '; border-color:' + colors.borderColor;
style += '; border-width: 2px';
var span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';
innerHtml += '<tr><td>' + span + body + '</td></tr>';
});
innerHtml += '</tbody>';
var tableRoot = tooltipEl.querySelector('table');
tableRoot.innerHTML = innerHtml;
}
// find relative proportion
var dataIndex = tooltip.dataPoints[0].index;
var datasetIndex = tooltip.dataPoints[0].datasetIndex;
var totalHeight = 0;
var thisHeight = this._chart.config.data.datasets[datasetIndex].data[dataIndex];
for (var i = 0; i <= datasetIndex; i++)
{
totalHeight += this._chart.config.data.datasets[i].data[dataIndex];
}
var positionY = this._chart.canvas.offsetTop;
var positionX = this._chart.canvas.offsetLeft;
var chartHeight = this._chart.canvas.scrollHeight;
var tooltipHalfHeight = tooltip.height / 2;
// Display, position, and set styles for font
tooltipEl.style.opacity = 1;
tooltipEl.style.left = positionX + tooltip.caretX + 'px';
tooltipEl.style.top = tooltip.caretY + ((chartHeight - tooltip.caretY - positionY) * (thisHeight / totalHeight / 2)) - tooltipHalfHeight + 'px';
tooltipEl.style.fontFamily = tooltip._fontFamily;
tooltipEl.style.fontSize = tooltip.fontSize;
tooltipEl.style.fontStyle = tooltip._fontStyle;
tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
};
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["This", "That", "Something else", "Important thing", "Oh really?", "What!!"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}, {
data: [2, 5, 13, 5, 3, 4],
backgroundColor: [
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
},
tooltips: {
enabled: false,
custom: customTooltips,
}
}
});
</script>
</body>
</html>
&#13;
答案 1 :(得分:1)
您可能已经知道,要将自定义工具提示放在条形图的中心,您可能需要其中一些的 (条形)属性,例如 - 宽度,高度,顶部和左侧位置。但不幸的是,没有直接获得这些属性的方法,而是你需要自己计算它们。
要获取/计算这些属性,可以使用以下函数(可以命名为任何内容),它将返回一个包含所有这些(宽度,高度,顶部,左侧)属性的对象。特别是酒吧,当盘旋时。
function getBAR(chart) {
const dataPoints = tooltipModel.dataPoints,
datasetIndex = chart.data.datasets.length - 1,
datasetMeta = chart.getDatasetMeta(datasetIndex),
scaleBottom = chart.scales['y-axis-0'].bottom,
bar = datasetMeta.data[dataPoints[0].index]._model,
canvasPosition = chart.canvas.getBoundingClientRect(),
paddingLeft = parseFloat(getComputedStyle(chart.canvas).paddingLeft),
paddingTop = parseFloat(getComputedStyle(chart.canvas).paddingTop),
scrollLeft = document.body.scrollLeft,
scrollTop = document.body.scrollTop;
return {
top: bar.y + canvasPosition.top + paddingTop + scrollTop,
left: bar.x - (bar.width / 2) + canvasPosition.left + paddingLeft + scrollLeft,
width: bar.width,
height: scaleBottom - bar.y
}
}
检索所需属性后,您可以计算条形图的中心位置:
= - +( - /)
= - +( - /)
然后,创建自定义工具提示元素并相应地进行定位。
const chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr'],
datasets: [{
label: 'Revenue',
data: [4, 2, 3, 3],
backgroundColor: '#2d4e6d'
}, {
label: 'Expenses',
data: [3, 3.5, 4, 1],
backgroundColor: '#c06526'
}, {
label: 'Profit',
data: [3, 2.5, 4, 2],
backgroundColor: '#e0ecf0'
}]
},
options: {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true
}
}]
},
tooltips: {
enabled: false,
custom: function(tooltipModel) {
/*** jQuery IS USED FOR SIMPLICITY ***/
/* TOOLTIP & CARET ELEMENT */
let tooltip = $('#tooltip');
let tooltipCaret = $('#tooltip-caret');
/* CREATE TOOLTIP & CARET ELEMENT AT FIRST RENDER */
if (!tooltip.length && !tooltipCaret.length) {
tooltip = $('<div></div>').attr('id', 'tooltip');
tooltipCaret = $('<div></div>').attr('id', 'tooltip-caret');
$('body').append(tooltip, tooltipCaret);
}
/* HIDE IF NO TOOLTIP */
if (!tooltipModel.opacity) {
tooltip.hide();
tooltipCaret.hide();
return;
}
/* GET BAR PROPS (width, height, top, left) */
const barWidth = getBAR(this._chart).width,
barHeight = getBAR(this._chart).height,
barTop = getBAR(this._chart).top,
barLeft = getBAR(this._chart).left;
/* SET STYLE FOR TOOLTIP
(these can also be set in separate css file) */
tooltip.css({
"display": "inline-block",
"position": "absolute",
"color": "rgba(255, 255, 255, 1)",
"background": "rgba(0, 0, 0, 0.7)",
"padding": "5px",
"font": "12px Arial",
"border-radius": "3px",
"white-space": "nowrap",
"pointerEvents": "none"
});
/* SET STYLE FOR TOOLTIP CARET
(these can also be set in separate css file) */
tooltipCaret.css({
"display": "block",
"position": "absolute",
"width": 0,
"pointerEvents": "none",
"border-style": "solid",
"border-width": "8px 10px 8px 0",
"border-color": "transparent rgba(0, 0, 0, 0.7) transparent transparent"
});
/* ADD CONTENT IN TOOLTIP */
tooltip.text('ChartJS');
tooltip.append('<br><div class="color-box"></div><label style="display: block; margin: -16px 0 0 16px;"> Custom Tooltip<label>');
/* POSITION TOOLTIP & CARET
(position should be set after tooltip & caret is rendered) */
const centerX = barLeft + (barWidth / 2),
centerY = barTop + (barHeight / 2)
tooltip.css({
"top": centerY - (tooltip.outerHeight() / 2) + 'px',
"left": centerX + tooltipCaret.outerWidth() + 'px'
});
tooltipCaret.css({
"top": centerY - (tooltipCaret.outerHeight() / 2) + 'px',
"left": centerX + 'px'
});
/* FUNCTION TO GET BAR PROPS */
function getBAR(chart) {
const dataPoints = tooltipModel.dataPoints,
datasetIndex = chart.data.datasets.length - 1,
datasetMeta = chart.getDatasetMeta(datasetIndex),
scaleBottom = chart.scales['y-axis-0'].bottom,
bar = datasetMeta.data[dataPoints[0].index]._model,
canvasPosition = chart.canvas.getBoundingClientRect(),
paddingLeft = parseFloat(getComputedStyle(chart.canvas).paddingLeft),
paddingTop = parseFloat(getComputedStyle(chart.canvas).paddingTop),
scrollLeft = document.body.scrollLeft,
scrollTop = document.body.scrollTop;
return {
top: bar.y + canvasPosition.top + paddingTop + scrollTop,
left: bar.x - (bar.width / 2) + canvasPosition.left + paddingLeft + scrollLeft,
width: bar.width,
height: scaleBottom - bar.y
}
}
}
}
}
});
.color-box{width:12px;height:12px;background:#c06526;display:inline-block;margin-top:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>
如果您希望将工具提示放在每个条形段的中心,请使用以下功能:
function getBARSegment(chart) {
const dataPoints = tooltipModel.dataPoints,
bar = chart.active[dataPoints[0].datasetIndex]._model,
canvasPosition = chart.canvas.getBoundingClientRect(),
paddingLeft = parseFloat(getComputedStyle(chart.canvas).paddingLeft),
paddingTop = parseFloat(getComputedStyle(chart.canvas).paddingTop),
scrollLeft = document.body.scrollLeft,
scrollTop = document.body.scrollTop;
return {
top: bar.y + canvasPosition.top + paddingTop + scrollTop,
left: bar.x - (bar.width / 2) + canvasPosition.left + paddingLeft + scrollLeft,
width: bar.width,
height: bar.base - bar.y
}
}
const chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr'],
datasets: [{
label: 'Revenue',
data: [4, 2, 3, 3],
backgroundColor: '#2d4e6d'
}, {
label: 'Expenses',
data: [3, 3.5, 4, 1],
backgroundColor: '#c06526'
}, {
label: 'Profit',
data: [3, 2.5, 4, 2],
backgroundColor: '#e0ecf0'
}]
},
options: {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true
}
}]
},
tooltips: {
enabled: false,
custom: function(tooltipModel) {
/*** jQuery IS USED FOR SIMPLICITY ***/
/* TOOLTIP & CARET ELEMENT */
let tooltip = $('#tooltip');
let tooltipCaret = $('#tooltip-caret');
/* CREATE TOOLTIP & CARET ELEMENT AT FIRST RENDER */
if (!tooltip.length && !tooltipCaret.length) {
tooltip = $('<div></div>').attr('id', 'tooltip');
tooltipCaret = $('<div></div>').attr('id', 'tooltip-caret');
$('body').append(tooltip, tooltipCaret);
}
/* HIDE IF NO TOOLTIP */
if (!tooltipModel.opacity) {
tooltip.hide();
tooltipCaret.hide();
return;
}
/* GET BAR PROPS (width, height, top, left) */
const barWidth = getBARSegment(this._chart).width,
barHeight = getBARSegment(this._chart).height,
barTop = getBARSegment(this._chart).top,
barLeft = getBARSegment(this._chart).left;
/* SET STYLE FOR TOOLTIP
(these can also be set in separate css file) */
tooltip.css({
"display": "inline-block",
"position": "absolute",
"color": "rgba(255, 255, 255, 1)",
"background": "rgba(0, 0, 0, 0.7)",
"padding": "5px",
"font": "12px Arial",
"border-radius": "3px",
"white-space": "nowrap",
"pointerEvents": "none"
});
/* SET STYLE FOR TOOLTIP CARET
(these can also be set in separate css file) */
tooltipCaret.css({
"display": "block",
"position": "absolute",
"width": 0,
"pointerEvents": "none",
"border-style": "solid",
"border-width": "8px 10px 8px 0",
"border-color": "transparent rgba(0, 0, 0, 0.7) transparent transparent"
});
/* ADD CONTENT IN TOOLTIP */
tooltip.text('ChartJS');
tooltip.append('<br><div class="color-box"></div><label style="display: block; margin: -16px 0 0 16px;"> Custom Tooltip<label>');
/* POSITION TOOLTIP & CARET
(position should be set after tooltip & caret is rendered) */
const centerX = barLeft + (barWidth / 2),
centerY = barTop + (barHeight / 2)
tooltip.css({
"top": centerY - (tooltip.outerHeight() / 2) + 'px',
"left": centerX + tooltipCaret.outerWidth() + 'px'
});
tooltipCaret.css({
"top": centerY - (tooltipCaret.outerHeight() / 2) + 'px',
"left": centerX + 'px'
});
/* FUNCTION TO GET BAR PROPS */
function getBARSegment(chart) {
const dataPoints = tooltipModel.dataPoints,
bar = chart.active[dataPoints[0].datasetIndex]._model,
canvasPosition = chart.canvas.getBoundingClientRect(),
paddingLeft = parseFloat(getComputedStyle(chart.canvas).paddingLeft),
paddingTop = parseFloat(getComputedStyle(chart.canvas).paddingTop),
scrollLeft = document.body.scrollLeft,
scrollTop = document.body.scrollTop;
return {
top: bar.y + canvasPosition.top + paddingTop + scrollTop,
left: bar.x - (bar.width / 2) + canvasPosition.left + paddingLeft + scrollLeft,
width: bar.width,
height: bar.base - bar.y
}
}
}
}
}
});
.color-box{width:12px;height:12px;background:#c06526;display:inline-block;margin-top:5px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="ctx"></canvas>
答案 2 :(得分:0)
Chartjs 2.8 允许您为工具提示添加自定义位置模式。有了这个,您可以创建一个中心位置选项:
char *
有关工作示例,请参见小提琴:https://jsfiddle.net/astroash/wk5y0fqd/36/