【问题标题】:How can I draw a line to the highest datapoint in chart js?如何在图表 js 中绘制一条线到最高数据点?
【发布时间】:2019-05-11 22:11:02
【问题描述】:

我一直在使用 Chart JS 文档,但我认为这可能更多是基于问题的计算机科学/数学。我正在尝试绘制一条从图表底部延伸到最高数据点顶部的线。这是一个工作代码示例的链接:https://stackblitz.com/edit/react-pvzbwc

这个想法是让图表看起来像这样,点正好在数据的顶部结束:https://i.stack.imgur.com/L8d0H.jpg

以下是我的 after draw 钩子:

// draw a line when someone hovers over a data point
afterDatasetDraw: (chart) => {
          // console.log(chart)
          if (chart.tooltip._active && chart.tooltip._active.length) {
            const activePoint = chart.tooltip._active[0];
            console.log(activePoint.tooltipPosition())
            const ctx = chart.ctx;
            const y_axis = chart.scales['y-axis-0'];
            const x = activePoint.tooltipPosition().x;
            const yData = activePoint._chart.config.data.datasets[activePoint._datasetIndex].data[activePoint._index].y;

            const topY = y_axis.top;
            const bottomY = y_axis.bottom;
            // draw line
            ctx.save();
            ctx.beginPath();
            ctx.moveTo(x, topY);
            ctx.lineTo(x, bottomY);
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#000';
            ctx.stroke();
            ctx.restore();
         }
        }

当我需要在顶部画一条直线时效果很好,但当我只想在最高数据点的顶部看到它时就不行了。我注意到 topY 是一个静态不变的数字。我想知道是否有一种方法可以根据图表的笛卡尔点计算顶部位置?

绝对赞赏任何见解。

【问题讨论】:

    标签: javascript html5-canvas chart.js react-chartjs


    【解决方案1】:

    经过一番挣扎,我已经回答了这个问题。这比我提出的问题要简单得多。事实证明,我只需要计算数据点与图形之间的比率(以像素为单位),然后在该点处实现一条线。

    我已经使用 API 将其放入 plugin

    /// default values
    lineHeightAnnotation: {
      // defaults to have line to the highest data point on every tick
      always: true,
      // optionally, only have line draw to the highest datapoint nearest the user's hover position
      hover: false,
      // colors of the line
      color: '#000',
      // name of yAxis
      yAxis: 'y-axis-0',
      // weight of the line
      lineWeight: 1.5,
       /// sets shadow for ALL lines on the canvas
      shadow: {
        // color of the shadow
        color: 'rgba(0,0,0,0.35)',
        // blur of the shadow
        blur: 10,
        /// shadow offset
        offset: {
          // x offset
          x: 0,
          // y offset
          y: 3
        }
      },
      // dash defaults at [10, 10]
      noDash: true,
    }
    

    逻辑:

    /**
     * Vars
     * maxY - the tallest data point on the graph
     * tickMax - the tallest tick on the y axis
     * bottomY - the lowest point of the graph
     * additionalOffsets = dataset.borderWidth * 2
     * 
     *                               bottomY * maxY      
     * highestDataY =   bottomY -  -------------------   + additionOffsets
     *                                   tickMax
     */
    

    功能:

       afterDatasetDraw: (chart) => {
          // draw a dashed line when someone hovers over a data point
          if (chart.tooltip._active && chart.tooltip._active.length) {
            const activePoint = chart.tooltip._active[0];
            const ctx = chart.ctx;
    
            const x = activePoint.tooltipPosition().x;
            const yAxis = chart.scales['y-axis-0'];
    
            const tickMax = yAxis.ticksAsNumbers[0] // first index is always the tallest
            const tickLow = yAxis.ticksAsNumbers[yAxis.ticksAsNumbers.length - 1]
            const topY = yAxis.top; // clientRect.top + chart.padding.y
            const bottomY = yAxis.bottom; // clientRect.bottom
    
            let maxY = 1;
            let borderWidth = 0;
            const datasets = chart.config.data.datasets
            datasets.forEach((set, i) => {
              // get maximum Y value
              // get borderWidth of that dataset
              let point = set.data[activePoint._index].y
              if(point > maxY) {
                maxY = parseInt(point, 10) - parseInt(set.borderWidth, 10)
                borderWidth = parseInt(set.borderWidth, 10)
              }
            });
    
            let yBRatio = bottomY * (maxY - tickLow)
            let tMRatio = yBRatio / (tickMax - tickLow)
            let highestDataY = bottomY - tMRatio + (borderWidth * 2)
    
            // draw line
            ctx.save();
            ctx.beginPath();
            ctx.setLineDash([10, 10]);
            ctx.moveTo(x, highestDataY);
            ctx.lineTo(x, bottomY);
            ctx.lineWidth = 1.5;
            ctx.strokeStyle = '#000';
            ctx.stroke();
            ctx.restore();
          }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      • 2011-04-27
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      相关资源
      最近更新 更多