问题描述
我设法创建了一个自定义图例,以在图例的每个类别下显示系列。我可以访问名称,但是无法在图例中获得与名称一起呈现的符号。请指教。
import React,{ Component } from "react";
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 ReactDOM from "react-dom";
import { map,uniq,slice,filter,keyBy,uniqueId,at } from "lodash";
import { Menu,MenuDivider,MenuItem } from "@blueprintjs/core";
import { Row,Col } from "react-bootstrap";
import * as htmlToImage from "html-to-image";
import { saveAs } from "file-saver";
HC_more(Highcharts);
HC_exporting(Highcharts);
HC_series_label(Highcharts);
HC_boost(Highcharts);
const colors = [
"#800000","#9A6324","#808000","#469990","#000075","#e6194b","#f58231","#ffe119","#bfef45","#3cb44b","#42d4f4","#4363d8","#911eb4","#f032e6"
];
class Chart extends Component {
constructor(props) {
super(props);
const scenariosData = uniq(map(props.data.Series,"scenario"));
this.state = {
scenariosData
};
this.afterChart = this.afterChart.bind(this);
}
componentDidMount() {
const scenariosData = uniq(map(this.props.data.Series,"scenario"));
const mappedList = map(
uniq(map(this.props.data.Series,"scenario")),(item) => {
return {
name: item,ids: map(filter(this.props.data.Series,["scenario",item]),(data) =>
data.id.toString()
)
};
}
);
this.setState(
{
scenariosData,mappedList
},() => {
if (this.state.scenariosData.length === 1) {
const legendAreaContainer = document.querySelector("#legendArea");
ReactDOM.unmountComponentAtNode(legendAreaContainer);
} else {
if (scenariosData.length > 1) {
const mappednewList = keyBy(
this.internalChart.series,"userOptions.id"
);
const groupedData = map(mappedList,({ ids,...item }) => ({
...item,data: at(mappednewList,ids)
}));
this.internalChart.series.forEach((item) => {
const menu = (
// <Row>
// {map(this.state.mappedList,(scenario) => {
// return (
// <Col key={uniqueId()}>
// <Menu className="text-center">
// <MenuDivider title={scenario.name} />
// {scenario.ids.map((i) => {
// return (
// <MenuItem
// key={uniqueId()}
// text={`${i} - ${
// this.props.data.Series.find(
// (j) => j.id === Number(i)
// ).segment
// }`}
// style={{
// opacity: item.opacity,// color: colors[Number(i)]
// }}
// onClick={() => {
// alert(item.userOptions.id === Number(i));
// item.setVisible(!item.visible);
// item.opacity = item.visible ? 1 : 0.3;
// }}
// />
// );
// })}
// </Menu>
// </Col>
// );
// })}
// </Row>
<div className="row">
{map(groupedData,(scenario) => {
return (
<div key={uniqueId()} className="col">
<Menu className="text-center">
<MenuDivider title={scenario.name} />
{scenario.data.map((item) => {
return (
<MenuItem
key={uniqueId()}
text={
<div
style={{
backgroundColor: item.color,opacity: item.visible ? 1 : 0.3
}}
>
<div id="symbol">{item.name}</div>
</div>
}
labelElement={item.userOptions.id}
onClick={() => {
item.setVisible(!item.visible);
}}
/>
);
})}
</Menu>
</div>
);
})}
</div>
);
ReactDOM.render(menu,document.getElementById("legendArea"));
});
}
}
}
);
}
componentDidUpdate(prevProps) {
if (prevProps.data !== this.props.data) {
const scenariosData = uniq(map(this.props.data.Series,"scenario"));
const mappedList = map(
uniq(map(this.props.data.Series,(item) => {
return {
name: item,ids: map(
filter(this.props.data.Series,(data) => data.id.toString()
)
};
}
);
this.setState(
{
scenariosData,mappedList
},() => {
if (this.state.scenariosData.length === 1) {
const legendAreaContainer = document.querySelector("#legendArea");
ReactDOM.unmountComponentAtNode(legendAreaContainer);
} else {
if (scenariosData.length > 1) {
const mappednewList = keyBy(
this.internalChart.series,"userOptions.id"
);
const groupedData = map(
this.state.mappedList,...item }) => ({
...item,ids)
})
);
console.log("groupedData",groupedData);
this.internalChart.series.forEach((item) => {
const menu = (
<div className="row">
{map(groupedData,(scenario) => {
return (
<div key={uniqueId()} className="col">
<Menu className="text-center">
<MenuDivider title={scenario.name} />
{scenario.data.map((item) => {
return (
<MenuItem
key={uniqueId()}
text={
<div
style={{
backgroundColor: item.color,opacity: item.visible ? 1 : 0.3
}}
>
<div id="symbol">{item.name}</div>
</div>
}
labelElement={item.userOptions.id}
onClick={() => {
item.setVisible(!item.visible);
}}
/>
);
})}
</Menu>
</div>
);
})}
</div>
);
ReactDOM.render(menu,document.getElementById("legendArea"));
});
}
}
}
);
}
}
afterChart(chart) {
this.internalChart = chart;
this.forceUpdate();
}
render() {
const options = {
chart: {
zoomType: "x",resetZoomButton: {
position: {
align: "left",// by default
verticalAlign: "top",// by default
x: -10,y: 10
}
},type: "line",height: this.props.height ? this.props.height : `60%`,events: {}
},exporting: {
menuItemDeFinitions: {
// Custom deFinition
label: {
onclick: function () {
htmlToImage
.toBlob(document.getElementById("chartContainer"))
.then(function (blob) {
saveAs(blob,"my-node.png");
});
},text: "Download png"
}
},buttons: {
contextButton: {
menuItems: ["label"]
}
}
},title: {
text: this.props.title
},subtitle: {
text: ""
},yAxis: {
title: {
text: null
},labels: {
formatter: function () {
const self = this;
return Highcharts.numberFormat(self.value / 1,".");
},style: {
fontSize: "13px"
}
}
},legend:
this.state.scenariosData.length > 1
? {
enabled: false
}
: {
enabled: true,itemStyle: {
fontSize: "15px"
}
},credits: {
enabled: false
},xAxis: {
categories: map(this.props.data.Dates,(item) => item.Date),labels: {
style: {
fontSize: "13px"
}
}
},plotOptions: {
series: {
boostThreshold: 2000,label: {
enabled: false,connectorAllowed: false
},marker: {
enabled: false
}
}
},tooltip: {
pointFormatter: function () {
return Highcharts.numberFormat(this.options.y / 1,".");
}
},series: map(slice(this.props.data.Series,15),(item,index) => {
return {
name: this.state.scenariosData.length > 1 ? item.segment : item.name,data: item.values,type: this.props.chartType,id: item.id.toString(),color: colors[item.id - 1]
};
})
};
return (
<div id="chartContainer">
<HighchartsReact
highcharts={Highcharts}
options={options}
callback={this.afterChart}
{...this.props}
/>
<div id="legendArea" />
</div>
);
}
}
export default Chart;
请咨询。
这是我的codeandBox链接:https://codesandbox.io/s/intelligent-fog-cds4u?file=/src/Chart.jsx:0-12135
解决方法
我不确定最终的布局应该是什么样子,所以我只添加了符号,而没有在列中居中,请看一下:
https://codesandbox.io/s/bitter-currying-ibkdv
<div id="symbol">
{" "}
<div
style={{
backgroundColor: item.color,width: "20px",height: "20px",float: "left",borderRadius: "10px"
}}
></div>
{item.name}
</div>