[英]Highchart Legend with Checkbox, events, hover style, symbol order change
我目前在我的应用程序的Chart
组件中实现了 Highcharts,但我需要对图例进行一些更改,浏览大部分文档,使用Highcharts.wrap()
创建一些函数。
首先,Legend 很简单,每个 Legend 项目都是
但现在我需要将其更改为:
这是我到目前为止得到的:
并单击复选框复制单击图例(符号,标签),显示/隐藏系列线。
如何? 用这个:(仅显示重要部分)
const defaultOptions: Highcharts.Options = {
...,
legend: {
borderColor: "transparent",
verticalAlign: "top",
align: "left",
x: 14,
itemCheckboxStyle: {
cursor: "pointer",
border: "1px solid #62737a",
},
},
...,
plotOptions: {
series: {
...,
showCheckbox: true,
selected: true,
events: {
checkboxClick: function () {
this.setVisible(!this.visible);
},
},
},
...,
},
...,
}
如果我们只使用showCheckbox: true
,那么复选框将在每个 label 的右侧很远,并不理想。 所以这是需要的:(如果可能的话,我还想知道在这种情况下如何避免 TS 上的任何错误的提示,没有评论)。
Highcharts.wrap(Highcharts.Legend.prototype, "positionCheckboxes", legendCheckboxPosition);
function legendCheckboxPosition(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
p: any,
scrollOffset: number
) {
const alignAttr = this.group.alignAttr;
const clipHeight = this.clipHeight || this.legendHeight;
let translateY: number;
if (alignAttr) {
translateY = alignAttr.translateY;
Highcharts.each(
this.allItems,
function (item: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
checkbox: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
legendItem: { getBBox: (arg0: boolean) => any };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
checkboxOffset: any;
}) {
const checkbox = item.checkbox;
const bBox = item.legendItem.getBBox(true);
let top;
if (checkbox) {
top = translateY + checkbox.y + (scrollOffset || 0) + 2;
Highcharts.css(checkbox, {
left:
alignAttr.translateX +
item.checkboxOffset +
checkbox.x -
100 -
bBox.width +
17 +
"px",
top: top + "px",
display: top > translateY - 6 && top < translateY + clipHeight - 6 ? "" : "none",
});
}
}
);
}
}
但是完成此操作后,我仍然需要进行一些更改,它们是:
legends
选项中应该有一个rtl
属性,它应该更改Symbol和Label的顺序,但是如果我这样做,它会反转,但它也会反转图例的顺序不知何故,我会展示:->没有rtl
: 我理解的复选框距离,因为它需要更改我的legendCheckboxPosition
function,我真正的问题是更改图例的顺序,就像我使用legend.reversed: true
一样。我发现我可以使用reversed
属性要解决这个问题,但我想知道这是否是其他问题的错误..因为在文档中rtl
属性仅更改Symbol和Label的顺序,而不是图例的顺序。
:hover
中添加一个样式,我尝试使用legend.itemCheckboxStyle
但这不允许我添加hover效果...(悬停复选框时我需要放置一个框阴影)series.selected
属性确定,并且我在plotOptions.series.events
中有legendItemClick
事件,但在里面我没有this.setSelected
,只有this.setVisible
function。 我尝试使用它,但它似乎冻结了图表,没有做任何事情。 仅在图例项中单击时如何更改复选框选择? 编辑:设法通过将此事件添加到options.plotOptions.series.events
来解决此问题:
legendItemClick: function () {
const seriesIndex = this.index;
this.chart.series[seriesIndex].select();
},
嗯..这是我的问题,希望你们能帮助我解决它。
安排图例元素的一种可能方法是在legend.labelFormatter
中编辑图例并添加 Unicode 行字符。 要使右侧的复选框也可以在legend.itemCheckboxStyle
中设置样式。
legend: {
symbolWidth: 0,
useHTML: true,
labelFormatter: function() {
return `<div>${this.name}<span style="color: green;">━</span></div>`;
},
itemDistance: 50,
itemCheckboxStyle: {
"width": "13px",
"height": "13px",
"margin-left": "-130px",
"position": "absolute"
}
},
API 参考文献:
https://api.highcharts.com/highcharts/legend.itemCheckboxStyle
经过大量的研究和实验,我设法让这一切正常工作。
选项(默认选项和事件,还切换加载可见性)
const series = GetSeries(opts, null);
...
// Check if Series is supposed to be hidden from load (from the checkbox selected prop), if it is, hide it
series.forEach((serie) => {
if (serie.selected !== undefined && serie.selected === false) serie.visible = false;
});
const defaultOptions: Highcharts.Options = {
...,
legend: {
borderColor: "transparent",
verticalAlign: "top",
align: "left",
x: 14,
},
...,
plotOptions: {
series: {
...
showCheckbox: true,
selected: true,
events: {
checkboxClick: function () {
this.setVisible(!this.visible);
},
legendItemClick: function () {
const seriesIndex = this.index;
this.chart.series[seriesIndex].select();
},
},
},
...
},
...
};
return mergeObjects(defaultOptions, opts);
}
并且很多解决扩展 Highcharts :
// Adjust position of the Highchart Legend Checkbox, and switch label and symbol in the legend
function legendPositionAdjustments(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
p: any,
scrollOffset: number
) {
const pixelsToREM = (value: number) => {
return value / 16;
};
const alignAttr = this.group.alignAttr;
const clipHeight = this.clipHeight || this.legendHeight;
let translateY: number;
const legendMainElement = this.box.parentGroup.element;
// Adjust the main legend element to be closer to the checkbox
if (legendMainElement) {
Highcharts.attr(legendMainElement, "transform", "translate(19, 10)");
}
if (alignAttr) {
translateY = alignAttr.translateY;
this.allItems.forEach(function (item: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
checkbox: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
legendItem: { getBBox: (arg0: boolean) => any };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
checkboxOffset: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
legendGroup: any;
}) {
const bBox = item.legendItem.getBBox(true);
// Change position of Label and Symbol in the Highcharts Legend
const legendItemElement = item.legendGroup.element;
const legendItemPath = legendItemElement.querySelector("path.highcharts-graph");
const legendItemPoint = legendItemElement.querySelector("path.highcharts-point");
const legendItemText = legendItemElement.querySelector("text");
if (legendItemPath) {
Highcharts.attr(legendItemPath, "transform", `translate(${bBox.width + 3}, 0)`);
}
if (legendItemPoint) {
Highcharts.attr(legendItemPoint, "transform", `translate(${bBox.width + 3}, 0)`);
}
if (legendItemText) {
Highcharts.attr(legendItemText, "x", 0);
}
// Adjust the position of the checkbox to the left side of the Highcharts Legend
const checkbox = item.checkbox;
let top;
let left;
if (checkbox) {
top = translateY + checkbox.y + (scrollOffset || 0) + 4;
left = alignAttr.translateX + item.checkboxOffset + checkbox.x - 100 - bBox.width + 17;
Highcharts.css(checkbox, {
left: pixelsToREM(left) + "rem",
top: pixelsToREM(top) + "rem",
display: top > translateY - 6 && top < translateY + clipHeight - 6 ? "" : "none",
});
}
});
}
}
// This function is called when triggering show/hide of series, always calling with visibility = true
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
function colorizeLegendRegardlessOfVisibility(this: any, proceed: any, item: any, visible: any) {
proceed.call(this, item, true);
}
这将:
希望对以后遇到类似问题的人有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.