无法从Chart.js BoxAnnotation读取上下文元素的Y属性

ekqde3dh  于 12个月前  发布在  Chart.js
关注(0)|答案(1)|浏览(180)

我是Chart.js的新手,我做了大量的研究,但没有发现任何可以帮助我的东西,所以我向社区寻求帮助。
我正在使用Chart.js版本3.2.1和chartjs-plugin-annotation版本1.0.1处理一个项目。不幸的是,目前无法更新库。
场景如下:我需要用渐变填充BoxAnnotation插件的背景。好了,我知道怎么做了。问题是这个BoxAnnotation的位置会根据用户应用的过滤器而变化。因此,createLinearGradient的Y坐标需要在运行时从BoxAnnotation中获得。
现在的问题是,我无法读取上下文元素的Y属性。它总是返回undefined。因此,我无法正确设置渐变的起始位置。
下面是BoxAnnotation的代码:

boxDeficitStatus: !this.onlyVirtualSensors && {
    type: 'box',
    yScaleID: 'right-y-axis',
    drawTime: 'beforeDatasetsDraw',
    yMin: 0,
    yMax: $this.moistureCritical,
    backgroundColor: function(context) {
        const chart = context.chart;
        const {ctx, chartArea} = chart;

        return getGradient(ctx, chartArea);
    },
    borderWidth: 0,
    display: !this.onlyVirtualSensors,
}

字符串
下面是getGradient函数的代码:

function getGradient(ctx, chartArea) {
  const chartHeight = chartArea.bottom - chartArea.top;

  //Instead of 246, the Y coordinate value I'm trying to obtain should go there.
  const gradient = ctx.createLinearGradient(67.7, 246, 67.7, chartHeight);
  gradient.addColorStop(0, "rgba(255, 255, 255, 0.3)");
  gradient.addColorStop(1, "rgba(255, 0, 0, 0.3)");
  
  return gradient;
}


运行console.log('$context', context.element['$context'])
浏览器终端中的结果如您提供的图像所示:
x1c 0d1x的数据
但是,当尝试使用下列任一项存取Y属性时:

console.log('y', context.element['$context']['element'].y)
console.log('y', context.element.y)
console.log('y', context.element['y'])


其结果始终是未定义的。
我的问题是,是否有可能以某种方式访问这个Y属性,或者是否有另一种方法来获得我需要的坐标。
不客气!提前感谢您的耐心!

vzgqcmou

vzgqcmou1#

我成功地克服了这个挑战,我将与未来可能需要它的任何人分享解决方案。
问题是上下文中的“元素”的值是在图表初始化后立即计算的。因此,我需要找到一种方法在图表渲染后立即访问我需要的值。为了实现这一点,我使用了setTimeoutchart.update,正如我们的朋友@kikon所建议的那样。
最终的解决方案基本如下:

import { Component, OnInit } from '@angular/core';
import { Chart } from 'chart.js';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  myChart: Chart;
  chartCtx: any;
  elementCtx: any;

  ngOnInit() {
    this.plotChart();
    this.getStatusBoxCoordinates(this.elementCtx);
  }

  getStatusBoxCoordinates(element) {
    setTimeout(() => {
      const boxStatus=
        this.myChart.options.plugins.annotation.annotations[
          'boxStatus'
        ];
      boxStatus.backgroundColor = this.getGradient(
        element?.x,
        element?.y,
        this.chartCtx
      );
      this.myChart.update();
    }, 50);
  }

  getGradient(coordinateX, coordinateY, chart) {
    const { ctx, chartArea } = chart;
    const x = coordinateX || 0;
    const y0 = coordinateY || 0;
    const y1 = chartArea.bottom - 50 || 295;
    const gradient = ctx.createLinearGradient(x, y0, x, y1);
    gradient.addColorStop(0, 'rgba(255, 229, 229,0.1)');
    gradient.addColorStop(0.2, 'rgba(255, 198, 198,0.1)');
    gradient.addColorStop(0.4, 'rgba(252, 175, 175,.1)');
    gradient.addColorStop(0.6, 'rgba(249, 130, 130,0.1)');
    gradient.addColorStop(0.8, 'rgba(242, 109, 109, .1)');
    gradient.addColorStop(1, 'rgba(224, 76, 76, 0.1)');

    return gradient;
  }

  plotChart() {
    let $this = this;

    const xValues = [50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150];
    const yValues = [7, 8, 8, 9, 9, 9, 10, 11, 14, 14, 15];

    this.myChart = new Chart('myChart', {
      type: 'line',
      data: {
        labels: xValues,
        datasets: [
          {
            fill: false,
            backgroundColor: 'rgba(0,0,255,1.0)',
            borderColor: 'rgba(0,0,255,0.1)',
            data: yValues,
          },
        ],
      },
      options: {
        plugins: {
          annotation: {
            annotations: {
              boxStatus: {
                type: 'box',
                yScaleID: 'y',
                yMin: 0,
                yMax: 10,
                backgroundColor: function (context) {
                  $this.elementCtx = context.element;
                  $this.chartCtx = context.chart;
                  return 'rgba(255, 255, 255, 0)';
                },
              },
            },
          },
        },
      },
    });
  }
}

字符串
我利用整个组件中可访问的变量来存储boxStatus的上下文,然后在图表已经计算出y 0之后,基于此上下文更新backgroundColor。
好吧,就是这样!我希望这对将来的人有帮助!

相关问题