按类型分类的Highcharts图例的2列布局-React highcharts [英] 2 column layout for Highcharts legend categorized by type - React highcharts

查看:332
本文介绍了按类型分类的Highcharts图例的2列布局-React highcharts的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个图表,其中根据与JSON不同的scenario将图例分为几列.图例项目应归类到每个标题下,但从我所做的事情来看,标题始终总是放在每个图例项目之前.请指教.

这就是我所拥有的:

    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链接: 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/

反应版本: 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://codesandbox.io/s/fragrant-cherry-2qhr6?file=/src/App.js:0-25119 https://stackblitz.com/edit/react-7owjmq

Expected Output:

解决方案

After digging more into your requirement I decided that it will be better to position the already existed legend items and create the custom labels name than trying to render them in the custom legend. I added some comments in the code, so I think that everything is clearly explained - in case of any doubts feel free to ask.

Simple JS demo: https://jsfiddle.net/BlackLabel/8wnq2y4k/

React version: 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


If you want to try to implement the symbols to your custom legend here is a part of the code responsible for it: https://github.com/highcharts/highcharts/blob/master/js/Core/Legend.js#L479

这篇关于按类型分类的Highcharts图例的2列布局-React highcharts的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆