将工具提示放置在栏的中心 [英] Position tooltip in center of bar

查看:12
本文介绍了将工具提示放置在栏的中心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

找不到像这样将工具提示放置在栏中心的方法(是的,我知道它不完全在此屏幕截图的中心,但仍然):

如果我使用custom工具提示选项,我只能获得插入符号在栏顶部的xy位置。但无法获取条的高度/宽度。

下面是我传递给图表构造函数的Options对象的一部分:

const options = {
  tooltips: {
    enabled: false,
    custom: (tooltip) => {
      // Retrieving valuable props from tooltip (caretX, caretY)
      // and creating custom tooltip that is positioned
      // on top of a bar
    }
  }
  // other options
}

const chart = new Chart(ctx, {
  type: 'bar',
  data,
  options
})

推荐答案

您可能已经知道,要将自定义工具提示放置在栏的中心,您可能需要它的一些(栏)属性,例如-宽度、高度、顶部和左侧位置。但不幸的是,没有直接的方法来获取这些属性,而是需要您自己计算它们。

若要获取/计算这些属性,您可以使用以下函数(可以任意命名),该函数将返回一个对象,该对象包含特定条形图的所有这些(宽度、高度、顶部、左侧)属性。

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
   }
}

计算居中位置

检索所需属性后,您可以计算条形的中心位置,如下所示:

𝚌𝚎𝚗𝚝𝚎𝚛𝚇 = 𝚋𝚊𝚛-𝚕𝚎𝚏𝚝+(𝚋𝚊𝚛-𝚠𝚒𝚍𝚝𝚑/𝟸)

𝚌𝚎𝚗𝚝𝚎𝚛𝚈 = 𝚋𝚊𝚛-𝚝𝚘𝚙+(𝚋𝚊𝚛-𝚑𝚎𝚒𝚐𝚑𝚝/𝟸)

然后,创建自定义工具提示元素并相应地放置它。


ᴘʀᴇᴠɪᴇᴡ

ʟɪᴠᴇ ᴇxᴀᴍᴘʟᴇ

数据-lang="js"数据-隐藏="真"数据-控制台="假"数据-巴贝尔="假">
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
   }
}

ᴘʀᴇᴠɪᴇᴡ

ʟɪᴠᴇ ᴇxᴀᴍᴘʟᴇ

数据-lang="js"数据-隐藏="真"数据-控制台="假"数据-巴贝尔="假">
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>

这篇关于将工具提示放置在栏的中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆