Можно ли добавить вертикальную сюжетную линию и показать пересечение с серией? - PullRequest
1 голос
/ 14 апреля 2019

Я хочу знать, есть ли способ поставить линию на график и показать значения, которые пересекают эту линию из всех рядов

для этого я создал средство форматирования для меток данных серии, которое ищет каждую метку, если ее значение x является значением x линии графика, а затем отображает только метку данных

plotOptions: {
                        series: {
                            dataLabels: {
                                enabled: true,
                                className: 'highcharts-data-label-box',
                                padding: 0,
                                formatter: function () {
                                    if (valuesToShow.indexOf(this.x) > -1) {
                                        return this.y;
                                    } else {
                                        return null;
                                    }
                                }
                            }
}

это мое демо для этого: https://jsfiddle.net/rabigado/7wousgm5/118/

хотел бы найти способ сделать это с помощью аннотаций или другим, менее дорогостоящим способом достижения того же результата.

1 Ответ

1 голос
/ 15 апреля 2019

Пользовательские метки могут быть сделаны с использованием Highcharts.SVGRenderer. Однако при перерисовке диаграммы требуется дополнительная логика, поскольку метки меняют свои позиции, а более сложная группировка данных приближается к другим значениям при изменении экстремумов.

Мне удалось это сделать, вы можете придерживаться этого подхода:

  1. в point.events.click обратном вызове найти позицию x из целого группа точек. Вы можете найти его в массиве chart.series.xData. Обратите внимание, что chart.series.processedXData имеет значения, которые в данный момент отображаются на диаграмме - сгруппированы по dataGrouping.
  2. рендеринг plotLine в позиции x
  3. используйте chart.renderer.text, чтобы добавить метку для каждой серии. Спасти ссылка на созданный ярлык.
  4. в обратном вызове chart.events.render уничтожает существующие элементы SVG для каждой метки и перерисовать его с новой позицией и новым значением, когда dataGrouping изменит его.

Код:

добавление меток при нажатии точки:

point: {
  events: {
    click(event) {
      var chart = this.series.chart,
        seriesLen = chart.series.length,
        x = this.x,
        pointIndex,
        pointIndexAbs,
        i,
        y,
        annotation,
        absX,
        plotLine;

      absX = chart.series[0].xData.reduce(
        (prev, curr, index) => {
          return Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev;
        });

      plotLine = chart.xAxis[0].addPlotLine({
        color: "#000",
        width: 1,
        value: absX,
        id: absX
      });

      for (i = 0; i < seriesLen - 1; i++) {

        pointIndex = chart.series[i].processedXData.indexOf(x);

        if (pointIndex !== -1) {
          y = chart.series[i].processedYData[pointIndex];

          annotation = chart.renderer.text(
              y.toFixed(4).toString(),
              chart.xAxis[0].toPixels(absX) - 25,
              chart.yAxis[0].toPixels(y)
            )
            .css({
              fill: 'red',
              fontSize: '10px'
            })
            .attr({
              zIndex: 6
            })
            .add();

          chart.annotationColl.push({
            svgElem: annotation,
            x: absX,
            y: y,
            seriesIndex: i,
            plotLine: plotLine
          });
        }
      }

      return false;
    }
  }
}

перерисовать метки на событии рендеринга:

chart: {
  zoomType: 'xy',
  events: {
    render: function() {
      var chart = this,
        x,
        newX,
        newY,
        actualValue,
        absX,
        pointIndex,
        y;

      if (chart.annotationColl && chart.annotationColl.length) {

        chart.annotationColl.forEach(function(annotation, i) {
          if (annotation.svgElem) {
            annotation.svgElem.destroy();
          }

          absX = chart.series[0].processedXData.reduce(
            (prev, curr, index) => {
              return Math.abs(curr - annotation.x) < Math.abs(prev - annotation.x) ? curr : prev;
            });

          pointIndex = chart.series[annotation.seriesIndex].processedXData.indexOf(absX);
          y = chart.series[annotation.seriesIndex].processedYData[pointIndex];

          newX = chart.xAxis[0].toPixels(annotation.x) - 25;
          newY = chart.yAxis[0].toPixels(y);

          if (newX >= chart.plotLeft && newX < chart.plotLeft + chart.plotWidth - 35) {
            annotation.svgElem = chart.renderer.text(
                y.toFixed(4).toString(),
                newX,
                newY
              )
              .css({
                fill: 'red',
                fontSize: '10px'
              })
              .attr({
                zIndex: 6
              })
              .add();
          } else {
            annotation.svgElem = null;
          }
        });
      } else {
        chart.annotationColl = [];
      }

    }
  }
}

Демо-версия:

Ссылка API:

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