基于差异的两条线之间的颜色区域

Ørn*_*sen 3 javascript highcharts

我有一个包含两条线的图表,我想根据哪条线位于另一条线上方来为它们之间的区域着色。

该图显示了收入和结果,因此如果收入大于结果,则该区域为绿色,但如果结果大于收入,则该区域变为红色。

我找不到在 Highcharts 中执行此操作的好方法。我尝试过面积图,但它们只是从零到线着色。

我希望图片插图能有所帮助,并且有人知道如何做到这一点。

非常感谢。

我的两个数据集只是两个简单的数组,例如

let income = [0, 0, 0, 0, 1000, 1000, 2000, 5000, 9000]
let outcome = [0, 0, 0, 0, 0, 7000, 7000, 7000, 12000]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

ewo*_*den 6

通过使用区域,您可以更改沿所需轴的给定位置的颜色。这是语法:

series: {
    name: 'Income',
    data: data,
    zoneAxis: 'x',
    zones: [{value: 1, fillColor: 'green'}, 
            {value: 5, fillColor: 'red}
            ]
}
Run Code Online (Sandbox Code Playgroud)

该片段为您提供了两个区域,绿色最多为 1,红色从 1 到 5。由于手动执行此操作并不是很有趣,因此我制作了一个自动执行此操作的示例,请参阅小提琴或帖子底部:

http://jsfiddle.net/zhjyn2o4/1/

最后你会得到一个arearange像这样的图表: 高图表示例

我在 highstock 中做到了这一点,但如果您更喜欢使用 highchart,那么它应该使用相同的代码工作,尽管它看起来有点不同。

您可能会想更改为areasplinerange(看起来更好)。但使用样条线很难找到交点,因此很难正确为图形着色。

series: {
    name: 'Income',
    data: data,
    zoneAxis: 'x',
    zones: [{value: 1, fillColor: 'green'}, 
            {value: 5, fillColor: 'red}
            ]
}
Run Code Online (Sandbox Code Playgroud)
let income = [0, 0, 0, 1000, 1000, 2000, 5000, 9000, 12000, 12000, 12000, 5000, 4000, 10000]
let outcome = [0, 0, 7000, 0, 7000, 7000, 7000, 12000, 9000, 9000, 9000, 5000, 5000, 5000]

//create a function to find where lines intersect, to color them correctly
function intersect(x1, x2, y1, y2, y3, y4) {
  return ((x2 * y1 - x1 * y2) - (x2 * y3 - x1 * y4)) / ((y4 - y3) - (y2 - y1));
}

var ranges = []; //stores all the data for the graph like so [x, y1, y2]
var incomeZones = []; //stores the different zones based on where the lines intersect
var incomeBiggerBool = true; //used for keeping track of what current color is


//loop through all values in income and outcome array (assumes they are same length). Fill the ranges array and create color zones. 
//Zones color up to a given point, therefore we need to push a color at the end, before it intersects
for (i = 0; i < income.length; i++) {
  ranges.push([i, income[i], outcome[i]]); //push to range array

  if (income[i] < outcome[i] && incomeBiggerBool) {
    incomeZones.push({
      value: intersect(i - 1, i, income[i - 1], income[i], outcome[i - 1], outcome[i]),
      fillColor: '#C0D890', // green
    }); //push to zone array 
    incomeBiggerBool = false;
  } else if (income[i] > outcome[i] && !incomeBiggerBool) {
    incomeZones.push({
      value: intersect(i - 1, i, income[i - 1], income[i], outcome[i - 1], outcome[i]),
      fillColor: '#ED4337' // red
    }); //push to zone array 
    incomeBiggerBool = true;
  }
}
//zones color up to a given point, therefore we need to push a color at the end as well:
if (incomeBiggerBool) {
  incomeZones.push({
    value: income.length,
    fillColor: '#C0D890' // green
  })
} else {
  incomeZones.push({
    value: income.length,
    fillColor: '#ED4337' // red
  })
}

var chart = Highcharts.stockChart('container', {

  chart: {
    type: 'arearange'
  },
  credits: {
    enabled: false
  },
  exporting: {
    enabled: false
  },
  rangeSelector: {
    enabled: false
  },
  scrollbar: {
    enabled: false
  },
  navigator: {
    enabled: false
  },
  xAxis: {
    visible: false
  },
  title: {
    text: 'Example'
  },
  plotOptions: {},
  tooltip: {
    //Prettier tooltip:
    pointFormatter: function() {
      return 'Income: <b>' + this.low + '</b> -  Expenditures: <b>' + this.high + '</b>'
    }
  },
  series: [{
    name: 'Income',
    data: ranges,
    zoneAxis: 'x',
    zones: incomeZones
  }]
});
Run Code Online (Sandbox Code Playgroud)