按类型分类的 Highcharts 图例的 2 列布局 - React highcharts

2 column layout for Highcharts legend categorized by type - React highcharts

我想创建一个图表,其中图例根据 scenario 与 JSON 的不同分为多个列。图例项应归类在每个 header 下,但根据我所做的,header 总是被添加到每个图例项之前。请指教

这是我的:

    import React from "react";
    import "./styles.css";

    import * as Highcharts from "highcharts";
    import HighchartsReact from "highcharts-react-official";
    import HC_more from "highcharts/highcharts-more";
    import HC_exporting from "highcharts/modules/exporting";
    import HC_series_label from "highcharts/modules/series-label";
    import HC_boost from "highcharts/modules/boost";
    import { map, slice } from "lodash";

    HC_more(Highcharts);
    HC_exporting(Highcharts);
    HC_series_label(Highcharts);
    HC_boost(Highcharts);

    const App = (props) => {
      const options = {
        colors: [
          "#800000",
          "#9A6324",
          "#808000",
          "#469990",
          "#000075",
          "#e6194b",
          "#f58231",
          "#ffe119",
          "#bfef45",
          "#3cb44b",
          "#42d4f4",
          "#4363d8",
          "#911eb4",
          "#f032e6"
        ],
        chart: {
          zoomType: "x",
          resetZoomButton: {
            position: {
              align: "left", // by default
              verticalAlign: "top", // by default
              x: -10,
              y: 10
            }
          },
          type: "line",
          height: props.height ? props.height : `60%`
        },
        exporting: {
          enabled: true,
          chartOptions: {
            xAxis: [
              {
                max: null
              }
            ]
          }
        },
        title: {
          text: props.title
        },
        subtitle: {
          text: ""
        },
        yAxis: {
          title: {
            text: null
          },
          labels: {
            formatter: function () {
              return `${Highcharts.numberFormat(
                this.value / 1,
                props.decimalPlaces,
                "."
              )}`;
            },
            style: {
              fontSize: "13px"
            }
          }
        },
        legend: {
          itemStyle: {
            fontSize: "15px"
          },
          floating: false,
          itemMarginBottom: 5,
          width: 180,
          itemWidth: 100,
          useHTML: true,
          labelFormatter: function () {
            console.log(this);
            console.log(`data.Series[Number(this.userOptions.id)]`);
            return `<div>${
              data.Series[Number(this.userOptions.id) - 1].scenario
            }<div>${this.name}</div></div>`;
          }
        },
        credits: {
          enabled: false
        },
        xAxis: {
          categories: data.Dates.map((item) => item.Date),
          labels: {
            style: {
              fontSize: "13px"
            }
          }
        },
        plotOptions: {
          series: {
            boostThreshold: 2000,
            label: {
              enabled: false,
              connectorAllowed: false
            }
          }
        },
        tooltip: {
          pointFormatter: function () {
            return `${Highcharts.numberFormat(
              this.options.y / 1,
              props.decimalPlaces,
              "."
            )}`;
          }
        },
        series: map(slice(data.Series, 0, 15), (item) => {
          return {
            name: item.segment,
            data: item.values,
            type: "line",
            id: item.id.toString()
          };
        })
      };

      return (
        <HighchartsReact highcharts={Highcharts} options={options} {...props} />
      );
    };

    export default App;

Stackblitz Link:https://codesandbox.io/s/fragrant-cherry-2qhr6?file=/src/App.js:0-25119 https://stackblitz.com/edit/react-7owjmq

预期输出:

在深入了解您的要求后,我决定定位已经存在的图例项并创建自定义标签名称比尝试在自定义图例中呈现它们更好。我在代码中添加了一些注释,所以我认为一切都解释清楚了 - 如有任何疑问,请随时提出。

简单的 JS 演示:https://jsfiddle.net/BlackLabel/8wnq2y4k/

React 版本:https://stackblitz.com/edit/react-djeehw

events: {
  render() {
    const chart = this;
    const labelsPos = 450;
    let firstColumnY = 50; // Distance from the chart to the legend
    let secondColumnY = 50; // Distance from the chart to the legend


    chart.legend.allItems.forEach(l => {
      // First column
      if (l.userOptions.scenario === 'Class 1') {
        let group = l.legendGroup;

        group.translate(-chart.plotWidth / 2 + chart.plotLeft + group.getBBox().width, firstColumnY);
        firstColumnY += 23; // Where 23 is a height of the one legend label
      }


      // Second column
      if (l.userOptions.scenario === 'Class 2') {
        let group = l.legendGroup;
        group.translate(chart.plotWidth / 2, secondColumnY);
        secondColumnY += 23; // Where 23 is a height of the one legend label
      }
    });
            
            // Keep labels position responsive by deleting them and render again
    if (chart.firstLabel && chart.secondLabel) {
      chart.firstLabel.destroy();
      chart.secondLabel.destroy();
    }
      chart.firstLabel = chart.renderer.label('Class 1', 0, labelsPos).css({
          'font-size': '22px'
        })
        .add();

      chart.secondLabel = chart.renderer.label('Class 2', chart.plotWidth, labelsPos).css({
          'font-size': '22px'
        })
        .add();
      chart.secondLabel.translate(chart.secondLabel.x - chart.secondLabel.getBBox().width + 10, labelsPos)
  }
}

API: https://api.highcharts.com/highcharts/chart.events.render

API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#label

API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#destroy

API: https://api.highcharts.com/class-reference/Highcharts.SVGElement#translate


如果您想尝试将符号实现到您的自定义图例中,这里是负责它的代码的一部分:https://github.com/highcharts/highcharts/blob/master/js/Core/Legend.js#L479