Временная диаграмма с высокими чартами, использующими х-диапазон с несколькими стеками - PullRequest
0 голосов
/ 27 октября 2018

Я использую Highcharts для создания графика временной шкалы, который показывает поток различных «состояний» с течением времени.Текущая реализация - http://jsfiddle.net/hq1kdpmo/8/ и выглядит как state chart.

Текущий код выглядит следующим образом:

Highcharts.chart('container', {
  "chart": {
    "type": "xrange"
  },
  "title": {
    "text": "State Periods"
  },
  "xAxis": {
    "type": "datetime"
  },
  "yAxis": [{
    "title": {
      "text": "Factions"
    },
    "categories": ["A", "B", "C", "D"],
    "reversed": true
  }],
  "plotOptions": {
    "xrange": {
      "borderRadius": 0,
      "borderWidth": 0,
      "grouping": false,
      "dataLabels": {
        "align": "center",
        "enabled": true,
        "format": "{point.name}"
      },
      "colorByPoint": false
    }
  },
  "tooltip": {
    "headerFormat": "<span style=\"font-size: 0.85em\">{point.x} - {point.x2}</span><br/>",
    "pointFormat": "<span style=\"color:{series.color}\">●</span> {series.name}: <b>{point.yCategory}</b><br/>"
  },
  "series": [{
    "name": "State A",
    "pointWidth": 20,
    "data": [{
      "x": 1540430613000,
      "x2": 1540633768100,
      "y": 0
    }, {
      "x": 1540191009000,
      "x2": 1540633768100,
      "y": 1
    }, {
      "x": 1540191009000,
      "x2": 1540530613000,
      "y": 2
    }, {
      "x": 1540530613000,
      "x2": 1540633768100,
      "y": 3
    }]
  }, {
    "name": "State B",
    "pointWidth": 20,
    "data": [{
      "x": 1540191009000,
      "x2": 1540430613000,
      "y": 0
    }, {
      "x": 1540530613000,
      "x2": 1540633768100,
      "y": 2
    }, {
      "x": 1540191009000,
      "x2": 1540330613000,
      "y": 3
    }]
  }, {
    "name": "State C",
    "pointWidth": 20,
    "data": [{
      "x": 1540330613000,
      "x2": 1540530613000,
      "y": 3
    }]
  }],
  "exporting": {
    "enabled": true,
    "sourceWidth": 1200
  }
});

Теперь я с нетерпением жду создания чего-то подобного (простите за мои навыки рисования) chart to be.

Здесь категории от A до D являются единственной осью у.Но я бы хотел сгруппировать переменное количество параллельных диапазонов.Случай использования состоит в том, что в любой момент времени может быть несколько состояний, а число состояний в любой момент времени является переменным.Как мне продолжать это делать?

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Мне удалось решить эту проблему благодаря поддержке самих Highcharts. Идея состоит в том, чтобы установить положение галочки на событии load и использовать labels.formatter для форматирования каждой отдельной метки.

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;
  }
}

И метки отформатированы как:

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/

0 голосов
/ 02 ноября 2018

Как я предлагал в комментарии выше, лучше использовать Highcharts Renderer и добавлять пользовательские метки, чем манипулировать элементами Dom, как вы делали в предыдущем ответе, потому что это гораздо более чистое решение.

Отключить метки по умолчанию:

  yAxis: [{
    title: {
      text: "Factions",
      margin: 35
    },
    categories: ["A", "B", "C", "D", "E"],
    tickPositions: tickPositions,
    lineWidth: 0,
    labels: {
      enabled: false
    },
    reversed: true
  }]

Добавление пользовательских меток в правильные позиции с помощью рендерера:

  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;
        }
      }
    }
  }

Демо: https://jsfiddle.net/wchmiel/vkz7o1hw/

0 голосов
/ 29 октября 2018

Чтобы создать такую ​​диаграмму, вам нужно будет добавить 12 yAxis (0-11) и установить правильные галочки и метки, чтобы отображались только категории A-D. Кроме того, настройте свойства plotOptions.pointPadding и plotOptions.groupPadding , чтобы автоматически устанавливать ширину точек (тогда series.pointWidth не должен быть определен).

Опции YAXIS:

  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
  }]

Демо-версия: https://jsfiddle.net/wchmiel/s9qefg7t/1/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...