简体   繁体   中英

Highcharts column category in X-axis using different Y-axis

I'm using a column chart to display average result. On the X-axis, I want to show the average vital of female users, male users and also both genders. However, the Y-axis range is quite different as the smallest reading is < 30 and the largest reading is > 1000 (BMR). This make the chart became harder to read as the columns of < 30 readings are almost invisible. How can I make the reading of > 1000(BMR) to use another Y-axis?

在此处输入图片说明

I've tried to use linkedTo in series

            {
                name: 'Male',
                linkedTo: ':previous',
                stack: 10,
                yAxis: 1,
                tooltip: { valueSuffix: ` of total {point.numOfUser} users` },
                dataLabels: { enabled: true },
                data: [this.state.maleAvrBmr],
            }, {
                name: 'Female',
                linkedTo: ':previous',
                stack: 11,
                yAxis: 1,
                tooltip: { valueSuffix: ` of total {point.numOfUser} users` },
                dataLabels: { enabled: true },
                data: [this.state.femaleAvrBmr],
            }, {
                name: 'Male & Female',
                linkedTo: ':previous',
                stack: 12,
                yAxis: 1,
                tooltip: { valueSuffix: ` of total {point.numOfUser} users` },
                dataLabels: { enabled: true },
                data: [this.state.allAvrBmr],
            }

but the X-axis categories is messed up as shown. 在此处输入图片说明

Any help is appreciated. Thanks in advance and sorry for my english.

This issue is quite difficult because each series can be bind to separate yAxis but there is no way to bind particular points in one series. The workaround is to add an additional series with null points so that one group of columns can be bind to the second yAxis:

  series: [{
    name: 'Tokyo',
    id: 'Tokyo',
    color: '#7BB5EC',
    data: [49.9, 71.5, null, 129.2]
  }, {
    name: 'New York',
    id: 'New York',
    color: '#000',
    data: [83.6, 78.8, null, 93.4]
  }, {
    name: 'London',
    id: 'London',
    color: '#90ED7D',
    data: [48.9, 38.8, null, 41.4]
  }, {
    name: 'Berlin',
    id: 'Berlin',
    color: '#F7A35B',
    data: [42.4, 33.2, null, 39.7]
  }, {
    linkedTo: 'Tokyo',
    yAxis: 1,
    color: '#7BB5EC',
    data: [null, null, 1006.4, null]
  }, {
    linkedTo: 'New York',
    yAxis: 1,
    color: '#000',
    data: [null, null, 906.2, null]
  }, {
    linkedTo: 'London',
    yAxis: 1,
    color: '#90ED7D',
    data: [null, null, 553.1, null]
  }, {
    linkedTo: 'Berlin',
    yAxis: 1,
    color: '#F7A35B',
    data: [null, null, 696.8, null]
  }]

Demo:

However, it causes another problem. The groups of columns are not properly centered, because null points take space. This issue can be resolved by adding a custom logic that will center the group without computing space for null points. Check demo and code posted below.

Code:

function centerColumns(chart) {
  var xAxis = chart.xAxis[0],
    categories = xAxis.categories,
    catLen = categories.length,
    catOffset = xAxis.width / catLen,
    catStart = catOffset / 2,
    sortedPoints = {},
    tempPoint1 = chart.series[0].points[0],
    tempPoint2 = chart.series[1].points[0],
    pointWidth = tempPoint1.pointWidth,
    spaceWidth = tempPoint2.barX - tempPoint1.barX - pointWidth,
    category,
    pointsLen,
    groupWidth,
    point,
    newX,
    cat,
    key,
    i;

  for (i = 0; i < catLen; i++) {
    sortedPoints[categories[i]] = {
      plotLeft: catStart + i * catOffset,
      points: []
    }
  }

  chart.series.forEach(function(series) {
    series.points.forEach(function(p) {
      cat = p.category;

      if (!p.isNull) {
        sortedPoints[cat].points.push(p);
      }
    });
  });

  for (key in sortedPoints) {
    category = sortedPoints[key];
    pointsLen = category.points.length;
    groupWidth =
      pointsLen * pointWidth + (pointsLen - 1) * spaceWidth;

    for (i = 0; i < pointsLen; i++) {
      point = category.points[i];
      newX = category.plotLeft - groupWidth / 2 +
        i * (pointWidth + spaceWidth);

      point.graphic.attr({
        x: newX
      });
    }
  }
}

...

chart: {
  type: 'column',
  height: 300,
  events: {
    render: function() {
      centerColumns(this);
    }
  }
}

Demo:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM