score:1

Accepted answer

i have managed to solve this thanks to support from highcharts themselves. the idea is to set the tick position on the load event and use the labels.formatter for formatting each individual label.

events: {
  load() {
    let labelgroup = document.queryselectorall('.highcharts-yaxis-labels');
    // nodevalue is distance from top
    let ticks = document.queryselectorall('.highcharts-yaxis-grid');
    let tickpositions = array.from(ticks[0].childnodes).map(
        function(node){
            return +node.attributes.d.nodevalue.split(" ")[2];
        }
    );
    let labelpositions = [];
    for(let i =1 ;i<tickpositions.length;i++){
        labelpositions.push((tickpositions[i] + tickpositions[i-1])/2);
    }
    labelgroup[0].childnodes[0].attributes.y.nodevalue = labelpositions[0] + parsefloat(labelgroup[0].childnodes[0].style["font-size"], 10) / 2;
    labelgroup[0].childnodes[1].attributes.y.nodevalue = labelpositions[1] + parsefloat(labelgroup[0].childnodes[1].style["font-size"], 10) / 2;
    labelgroup[0].childnodes[2].attributes.y.nodevalue = labelpositions[2] + parsefloat(labelgroup[0].childnodes[2].style["font-size"], 10) / 2;
    labelgroup[0].childnodes[3].attributes.y.nodevalue = labelpositions[3] + parsefloat(labelgroup[0].childnodes[3].style["font-size"], 10) / 2;
    labelgroup[0].childnodes[4].attributes.y.nodevalue = labelpositions[4] + parsefloat(labelgroup[0].childnodes[4].style["font-size"], 10) / 2;
  }
}

and the labels are formatted as:

labels: {
  formatter: function() {
    var chart = this.chart,
      axis = this.axis,
      label;

    if (!chart.yaxislabelindex) {
      chart.yaxislabelindex = 0;
    }
    if (this.value !== -1) {

      label = axis.categories[chart.yaxislabelindex];
      chart.yaxislabelindex++;

      if (chart.yaxislabelindex === groups.length) {
        chart.yaxislabelindex = 0;
      }

      return label;
    }
  },
}

fiddle at https://jsfiddle.net/yvnp4su0/42/

score:1

to create such a chart you will have to add 12 yaxis (0-11) and set proper ticks and labels so that only a-d categories will be plotted. additionally, adjust plotoptions.pointpadding and plotoptions.grouppadding properties to set points width automatically (series.pointwidth should be undefined then).

yaxis options:

  yaxis: [{
    title: {
      text: "factions"
    },
    categories: ["a", "b", "c", "d"],
    tickpositions: [-1, 2, 5, 8, 11],
    linewidth: 0,
    labels: {
      y: -20,
      formatter: function() {
        var chart = this.chart,
          axis = this.axis,
          label;

        if (!chart.yaxislabelindex) {
          chart.yaxislabelindex = 0;
        }

        if (this.value !== -1) {

          label = axis.categories[chart.yaxislabelindex];
          chart.yaxislabelindex++;

          if (chart.yaxislabelindex === 4) {
            chart.yaxislabelindex = 0;
          }

          return label;
        }
      },
    },
    reversed: true
  }]

demo: https://jsfiddle.net/wchmiel/s9qefg7t/1/

score:1

as i suggested in the comment above it is a better idea to use highcharts renderer and add custom labels than manipulate dom elements as you did in the previous answer, because it is a much cleaner solution.

disable default labels:

  yaxis: [{
    title: {
      text: "factions",
      margin: 35
    },
    categories: ["a", "b", "c", "d", "e"],
    tickpositions: tickpositions,
    linewidth: 0,
    labels: {
      enabled: false
    },
    reversed: true
  }]

add custom labels in proper positions using renderer:

  chart: {
    type: 'xrange',
    height: 500,
    marginleft: 60,
    events: {
        load: function() {
        this.customlabels = [];
      },
      render: function() {
        var chart = this,
          yaxis = chart.yaxis[0],
          categories = yaxis.categories,
          xoffset = 15,
          yoffset = 20,
          xpos = yaxis.left - xoffset,
          tickpositions = yaxis.tickpositions,
          text,
          label,
          ypos,
          tick1y,
          tick2y,
          i;

        for (i = 0; i < tickpositions.length - 1; i++) {
            if (chart.customlabels[i]) {
            chart.customlabels[i].destroy();
          }

          tick1y = yaxis.topixels(tickpositions[i]);
          tick2y = yaxis.topixels(tickpositions[i + 1]);
          ypos = (tick1y + tick2y) / 2 + yoffset;
          text = categories[i];

          label = chart.renderer.text(text, xpos, ypos)
            .css({
              color: '#ccc',
              fontsize: '14px'
            })
            .add();

          chart.customlabels[i] = label;
        }
      }
    }
  }

demo: https://jsfiddle.net/wchmiel/vkz7o1hw/


Related Query

More Query from same tag