Highcharts/Highstock:如何将工具提示位置移动到数据组的中心

Highcharts/Highstock:如何将工具提示位置移动到数据组的中心,highcharts,Highcharts,请看一下这个: 图表中有一系列区域范围类型和强制数据分组,如下所示: 很明显,工具提示指向组中的最小y值。但是,我需要工具提示来引用数据组中心的值(我不是指平均值)。同样,对于垂直十字线底部的滑动“标题”(在示例中不可能看到差异,但实际上我使用了更细粒度的数据) 所需内容的手绘草图: 为了进行实验,我的JSFIDLE包含Highcharts Tooltip.定位器函数的包装。(或者,我可以在highcharts图表选项中引入一个部分tooltip.positioner,但我更喜欢在原始tool

请看一下这个:

图表中有一系列区域范围类型和强制数据分组,如下所示:

很明显,工具提示指向组中的最小y值。但是,我需要工具提示来引用数据组中心的值(我不是指平均值)。同样,对于垂直十字线底部的滑动“标题”(在示例中不可能看到差异,但实际上我使用了更细粒度的数据)

所需内容的手绘草图:

为了进行实验,我的JSFIDLE包含Highcharts Tooltip.定位器函数的包装。(或者,我可以在highcharts图表选项中引入一个部分tooltip.positioner,但我更喜欢在原始tooltip.positioner函数周围有一个包装器,以便保留它提供的所有功能,并且只修改所述的y定位)。
,我原以为当光标悬停在图表上时包装器会执行,但事实并非如此。我也试过用“”代替“定位器”,但运气不好

Highcharts.wrap(Highcharts.Tooltip.prototype, 'positioner', function (proceed, args) {

    console.log("positioner wrapper executing"); // **** this does not run !!?? ***
    
    // how can I get to the point? Is it args.point?
    const start = args.point.dataGroup.start;
    const length = args.point.dataGroup.length;
    
    // index of the central point within the group:
    const cidx = Math.floor((start + length / 2.0)); 

    // get the that point from the series
    const cx = args.point.series.xData[cidx];
    const cy = args.point.series.yData[cidx];
   
    // Here I want to call the original positioner function
    // with the point coordinates { x: cx, y: cy }
    // but I don't know how. 
    proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});

$(function () {

    // generate some data
    const x0 = 2592000000;
    const dx = 86400000;
    const n = 900;
    let data = [
        [x0, 10, 20]
    ]; // initial value

    for (i = 1; i < n - 1; i++) { // construct n values of [timestamp, random, random]
        data[i] = [data[i - 1][0] + dx, 10 + Math.random() * 10, 20 + Math.random() * 10];
    }

    chart = new Highcharts.StockChart({
        chart: {
            renderTo: 'container',
        },
        series: [{
            name: 'data',
            data: data,
            type: 'arearange',
            dataGrouping: {
                forced: true,
            }
        }]
    });
});
Highcharts.wrap(Highcharts.Tooltip.prototype,'positioner',函数(继续,args){
console.log(“定位器包装器正在执行”);//****这不会运行***
//我怎么才能说到点子上呢?是args.point吗?
const start=args.point.dataGroup.start;
常量长度=args.point.dataGroup.length;
//组内中心点的索引:
常数cidx=数学楼层((起点+长度/2.0));
//从这一系列中获得这一点
常量cx=args.point.series.xData[cidx];
常数cy=args.point.series.yData[cidx];
//这里我想调用原始定位器函数
//点坐标为{x:cx,y:cy}
//但我不知道怎么做。
apply(这个,Array.prototype.slice.call(参数,1));
});
$(函数(){
//生成一些数据
常数x0=2592000000;
常数dx=86400000;
常数n=900;
让数据=[
[x0,10,20]
];//初始值
对于(i=1;i
编辑:我多次修改了文本和JSFIDLE代码,以澄清我的意图并避免JSFIDLE出现问题

我需要工具提示来引用数据组中心的值(我不是指平均值)

请注意,没有点,工具提示状态为点-在本例中,它们之间只是一条路径

好吧,我原以为包装器会在光标悬停在图表上时执行,但事实并非如此

查看此演示:,检查开发控制台并探索工具提示原型。您应该注意到,
定位器
不存在,这就是包装器无法工作的原因

相反,我鼓励使用
pointFormatter
回调来计算显示的值(高点和低点之间的平均值),并使用
定位器
回调来设置点之间的工具提示位置

演示:

工具提示:{
指针格式化程序(){
让点=这个,
输出=`● ${point.series.name}:${(point.high+point.low)/2}
`; 返回输出 }, 形状:“rect”, 定位器:功能(标签宽度、标签高度、点){ 让chart=this.chart, yAxis=chart.yAxis[0]; if(点isHeader){ 返回{ x:point.plotX+chart.plotLeft-labelWidth/2, y:点。情节 } }否则{ 设lowPxPos=point.plotY, highPxPos=yAxis.toPixels(point.high)-chart.plotTop; 返回{ x:point.plotX+chart.plotLeft+10, y:(高PXPOS+低PXPOS)/2-标签高度/2, 伊舍德尔:是的 }; } }, },
API:

API:


编辑


根据评论-有一个最终的解决方案:

谢谢,但是point.high和point.low之间的中间值对我的目的没有用处。我需要未分组序列数据中的可用信息。我需要访问位于分组数据中心X的特定点(在未分组数据系列中)的坐标。我想这需要访问该系列。这不可能吗?此外,正如我所说的,我更愿意使用包装器来保持原来的工具提示定位行为的其余部分,而不必重新实现这一点……让我们考虑一下这个基本演示:在这里,您可以访问该系列。你能告诉我你想说什么吗:
我需要未分组序列数据中的可用信息。我需要访问位于分组数据中心X的特定点(在未分组数据系列中)的坐标
是否要访问嵌套在某个分组范围内的数据?工具提示应在其悬停的数据组的中心索引处获取(X,y)参数。我的意思是在索引轮(point.dataGroup.start+point.dataGroup.length/2)。在我的新演示jsfiddle.net/jakobvinther/b27cdzrw中,在控制台中,您可以看到数据组的值被动态打印出来。也许我应该提到,该图表将在webapp中用于显示密集采样的信号。它使用series.arearange.data类型来指示动态范围(最小/最大),无论缩放级别如何。系列数据数组如下所示:[[x1,y1,y1],[x2,y2,y2],[x3,y3,y3],…];注意两个y值(假设为Yman
tooltip: {
  pointFormatter() {
    let point = this,
      output = `<span style="color:${point.color}">●</span> ${point.series.name}: <b>${(point.high + point.low) / 2}</b><br/>`;

    return output
  },
        shape: 'rect',
  positioner: function(labelWidth, labelHeight, point) {
    let chart = this.chart,
      yAxis = chart.yAxis[0];

    if (point.isHeader) {
      return {
        x: point.plotX + chart.plotLeft - labelWidth / 2,
        y: point.plotY
      }
    } else {
      let lowPxPos = point.plotY,
        highPxPos = yAxis.toPixels(point.high) - chart.plotTop;

      return {
        x: point.plotX + chart.plotLeft + 10,
        y: (highPxPos + lowPxPos) / 2 - labelHeight / 2,
        isHeader: true
      };
    }
  },
},