Angular-Chart-JS-折线图,根据点的范围具有不同的填充颜色 [英] Angular-Chart-JS - Line chart with different fill colors according to points' range

查看:156
本文介绍了Angular-Chart-JS-折线图,根据点的范围具有不同的填充颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Angular-Chart-js来显示某些类型的图形,其中一种是折线图。

I'm using Angular-Chart-js for my website to display some types of graphs, one of them is a line chart.

我想要折线要填充颜色的图表,但根据y轴的值使用不同的颜色。就像这张照片:

I would like the line chart to be color-filled, but with different colors according to the y-axis' value. Like in this photo:

我试图在数据中使用不同的数据数组图的数组,第一个具有所有值,第二个具有除绿色以外的所有值(在右侧),第三个具有相同的数组,直到紫色范围等,然后每个数据集都有自己的颜色,但最终我根据最后的数据集颜色得到了具有单一颜色的图形。

I've tried to have different data arrays in the "data" array of the graph, the first one has all the values, the second one has all but the ones painted in green (on the right), the third is the same array only until the purple range etc. and then have for each dataset its own color, but eventually I get a graph with a single color according to the last dataset color.

我缺少什么?

谢谢。

推荐答案

不幸的是,您无法使用当前的chart.js配置选项实现此目的。原因是因为折线图 backgroundColor 选项(控制折线图填充颜色的选项)仅接受单个值。

Unfortunately, you cannot achieve this with the current chart.js configuration options. The reason is because the line chart backgroundColor option (the option that controls the color of the line chart fill) only accepts a single value.

在浏览了当前的chart.js 2.5源代码之后,我发现可以扩展line元素的 draw()方法并强制执行chart.js使用画布线性渐变进行填充(而不是仅使用一种颜色)。只需一点数学,我们就可以将每个点的x位置转换为线性渐变颜色停止位置并构建渐变。

After digging through the current chart.js 2.5 source, I found that it is possible to extend the line element's draw() method and force chart.js to use a canvas linear gradient for the fill (instead of just a single color). With a little bit of math, we can convert the x position of each point into a linear gradient color stop position and build a gradient.

有了此增强功能,您现在可以将颜色数组传递给折线图 backgroundColor 选项,以实现不同的彩色填充区域。这是一个结果图表的示例。

With this enhancement, you can now pass in an array of colors to the line chart backgroundColor option to achieve varying colored fill regions. Here is an example of what a resulting chart would look like.

以下是实际操作方法(底部有一个工作示例)

首先,我们必须扩展 Chart.elements.Line 并覆盖它的 draw()方法,以便我们可以根据位置构建线性渐变每个点中的每个点,将其用作线填充,然后绘制线。

First, we must extend Chart.elements.Line and overwrite it's draw() method so that we can build the linear gradient based upon the position of each point, use it as the line fill, and then draw the line.

// save the original line element so we can still call it's 
// draw method after we build the linear gradient
var origLineElement = Chart.elements.Line;

// define a new line draw method so that we can build a linear gradient
// based on the position of each point
Chart.elements.Line = Chart.Element.extend({
  draw: function() {
    var vm = this._view;
    var backgroundColors = this._chart.controller.data.datasets[this._datasetIndex].backgroundColor;
    var points = this._children;
    var ctx = this._chart.ctx;
    var minX = points[0]._model.x;
    var maxX = points[points.length - 1]._model.x;
    var linearGradient = ctx.createLinearGradient(minX, 0, maxX, 0);

    // iterate over each point to build the gradient
    points.forEach(function(point, i) {
      // `addColorStop` expects a number between 0 and 1, so we
      // have to normalize the x position of each point between 0 and 1
      // and round to make sure the positioning isn't too percise 
      // (otherwise it won't line up with the point position)
      var colorStopPosition = roundNumber((point._model.x - minX) / (maxX - minX), 2);

      // special case for the first color stop
      if (i === 0) {
        linearGradient.addColorStop(0, backgroundColors[i]);
      } else {
        // only add a color stop if the color is different
        if (backgroundColors[i] !== backgroundColors[i-1]) {
          // add a color stop for the prev color and for the new color at the same location
          // this gives a solid color gradient instead of a gradient that fades to the next color
          linearGradient.addColorStop(colorStopPosition, backgroundColors[i - 1]);
          linearGradient.addColorStop(colorStopPosition, backgroundColors[i]);
        }
      }
    });

    // save the linear gradient in background color property
    // since this is what is used for ctx.fillStyle when the fill is rendered
    vm.backgroundColor = linearGradient;

    // now draw the lines (using the original draw method)
    origLineElement.prototype.draw.apply(this);
  }               
});

然后,我们还必须扩展折线图以确保图表使用的折线元素为我们上面扩展的那个(因为此属性已在加载时设置)

Then, we have to also extend the line chart to ensure that the line element used by the chart is the one that we extended above (since this property is already set at load time)

// we have to overwrite the datasetElementType property in the line controller
// because it is set before we can extend the line element (this ensures that 
// the line element used by the chart is the one that we extended above)
Chart.controllers.line = Chart.controllers.line.extend({
  datasetElementType: Chart.elements.Line,
});

完成此操作后,我们现在可以将颜色数组传递给折线图 backgroundColor 属性(而不是单个值)来控制行填充。

With this done, we can now pass in an array of colors to the line chart backgroundColor property (instead of just a single value) to control the line fill.

这里是 codepen示例,它演示了所有已讨论的内容。

Here is a codepen example that demonstrates all that has been discussed.

注意事项:


  • 这种方法可能会在将来的chart.js版本中中断,因为我们正在弄乱内部结构。

  • 我不熟悉 angular-chart.js ,所以我无法提供有关如何将以上chart.js更改集成到angular指令中的见识。

  • This approach could break in future chart.js releases since we are messing with the internals.
  • I'm not familiar with angular-chart.js, so I cannot provide insight on how to integrate the above chart.js changes into the angular directive.

这篇关于Angular-Chart-JS-折线图,根据点的范围具有不同的填充颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆