我在一个带有jQuery-UI标签导航系统的网页上有3个Highcharts图表 - 每个标签一个图表。在仅其中一个图表中,我在绘制的线条上添加了一个箭头。此箭头在IIFE内生成(请参阅下面的代码示例)。否则 Highcharts功能非常标准。
当我尝试切换标签并显示其他两个图表的数据时会出现问题:箭头正在不应该有任何箭头的图表上绘制。
错误的箭头始终总是在其他图表上绘制 - 从不在第一次渲染时,通常只有在用户切换标签两次或三次后,才会出现箭头所在的位置“T。我还注意到每次渲染图表时都会调用此IIFE(即使是从其他选项卡中调用)。
我不知道Highcharts如何在内部工作,但我的每个图表都附加到一个不同的DOM元素(通过ID),因此Highcharts不应该在渲染箭头时混合图表。
有谁知道为什么会这样?
(function (H) {
var arrowCheck = false, //This variable helps the arrow to be responsive
pathTag;
H.wrap(H.Series.prototype, 'drawGraph', function (proceed) {
// Now apply the original function with the original arguments,
// which are sliced off this function's arguments
// This section takes care of the arrow of the graph
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var arrowLength = 14,
arrowWidth = 7,
series = this,
data = series.data,
segments = data,
lastSeg = segments[segments.length - 1],
path = [],
lastPoint = null,
nextLastPoint = null;
if (typeof (lastSeg) === "undefined") {
return;
}
if (lastSeg.y === 0) {
lastPoint = segments[segments.length - 2];
nextLastPoint = segments[segments.length - 1];
} else {
lastPoint = segments[segments.length - 1];
nextLastPoint = segments[segments.length - 2];
}
var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
(lastPoint.plotY - nextLastPoint.plotY));
if (angle < 0) angle = Math.PI + angle;
path.push('M', lastPoint.plotX, lastPoint.plotY);
if (lastPoint.plotX > nextLastPoint.plotX) {
if (arrowCheck === true) {
pathTag = doc.getElementById("arrow");
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
'L',
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX + arrowLength * Math.sin(angle),
lastPoint.plotY + arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX - arrowWidth * Math.cos(angle),
lastPoint.plotY + arrowWidth * Math.sin(angle),
'Z'
);
} else {
if (arrowCheck === true) {
pathTag = doc.getElementById("arrow");
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
lastPoint.plotY + arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX - arrowLength * Math.sin(angle),
lastPoint.plotY - arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle),
'Z'
);
}
series.chart.renderer.path(path)
.attr({
fill: series.color,
id: 'arrow'
})
.add(series.group);
arrowCheck = true;
});
}(Highcharts));
这是一个JSFiddle示例(您只需要调整图表所在的部分,以查看箭头如何跳转到错误的图表)
答案 0 :(得分:1)
简而言之,问题实际上是双重的:
所以......当您第一次绘制图表时,箭头会添加到第二个图表中。然后删除。然后添加到第一个图表(因为这是您在代码中拥有它们的顺序)。所以此时你会看到第一张图表上的箭头,而不是第二张图表上的箭头。
当HighCharts检测到需要调整大小时,它会重绘图表。但是在图表内部,图表的顺序不同,因此绘制第一个图表(这个图表需要箭头),首先删除带id="arrow"
的箭头,然后重新添加。现在第二个图表重绘:它删除了id="arrow"
的任何箭头(即使它现在碰巧在另一个图表上),然后将其添加到其图表中。现在箭头出现在图表2上。
这就是为什么它从一个交换到另一个的原因。该怎么办?
首先,如果您希望在该特定图表中包含箭头,请将参数添加到图表的plotOptions
。请注意,您可以在多个图表上执行此操作:
...
plotOptions: {
showArrow: true // signals that this chart requires an arrow
},
...
其次,检测此设置并仅在其存在时进行处理:
(function(H) {
var arrowCheck = false,
pathTag;
H.wrap(H.Series.prototype, 'drawGraph', function(proceed) {
// Now apply the original function with the original arguments,
// which are sliced off this function's arguments
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
if (this.chart.options.plotOptions.showArrow) {
// used a bit of regex to clean up the series name enough to be used as an id
var arrowName = "arrow" + this.name.replace(/\W/g, "_").toLowerCase();
var arrowLength = 15,
arrowWidth = 9,
series = this,
data = series.data,
len = data.length,
segments = data,
lastSeg = segments[segments.length - 1],
path = [],
lastPoint = null,
nextLastPoint = null;
if (lastSeg.y == 0) {
lastPoint = segments[segments.length - 2];
nextLastPoint = segments[segments.length - 1];
} else {
lastPoint = segments[segments.length - 1];
nextLastPoint = segments[segments.length - 2];
}
var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
(lastPoint.plotY - nextLastPoint.plotY));
if (angle < 0) angle = Math.PI + angle;
path.push('M', lastPoint.plotX, lastPoint.plotY);
if (lastPoint.plotX > nextLastPoint.plotX) {
if (arrowCheck === true) {
//replaced 'arrow' with arrowName
pathTag = document.getElementById(arrowName);
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
'L',
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX + arrowLength * Math.sin(angle),
lastPoint.plotY + arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX - arrowWidth * Math.cos(angle),
lastPoint.plotY + arrowWidth * Math.sin(angle),
'Z'
);
} else {
if (arrowCheck === true) {
//replaced 'arrow' with arrowName
pathTag = document.getElementById(arrowName);
if (pathTag != null) {
pathTag.remove(pathTag);
}
}
path.push(
'L',
lastPoint.plotX - arrowWidth * Math.cos(angle),
lastPoint.plotY + arrowWidth * Math.sin(angle)
);
path.push(
lastPoint.plotX - arrowLength * Math.sin(angle),
lastPoint.plotY - arrowLength * Math.cos(angle)
);
path.push(
lastPoint.plotX + arrowWidth * Math.cos(angle),
lastPoint.plotY - arrowWidth * Math.sin(angle),
'Z'
);
}
series.chart.renderer.path(path)
.attr({
fill: series.color,
id: arrowName //changed from 'arrow' to arrowName to enable more than one series with an arrow
})
.add(series.group);
arrowCheck = true;
}
});
}(Highcharts));
最后,请注意我已使用https://stackoverflow.com/a/39925450/1544886中的提示确保每个图表都有箭头的唯一元素ID。