高图表 有没有办法在缩放后调整绘图带的大小

Highcharts Is there a way to resize plotbands after zoom?

本文关键字:绘图 调整 有没有 缩放 高图表      更新时间:2023-09-26

我正在做这样的事情,以便在图表呈现时调整我的绘图带的大小:

  var _Chart = new Highcharts.Chart( options, function ( chart ) {
     for ( var i = 0; i < chart.xAxis[0].plotLinesAndBands.length; i++ ) {
         var band = chart.xAxis[0].plotLinesAndBands[i].svgElem, path = band.d.split(' ');
         var bottomString = chart.xAxis[0].plotLinesAndBands[i].options.iMBottom + '';
         var topString = chart.xAxis[0].plotLinesAndBands[i].options.iMTop + '';
         path[2] = bottomString;
         path[path.length - 1] = bottomString;
         path[5] = topString;
         path[7] = topString;
         band.attr('d', path);
      }
  });

这允许我设置图表 Y 轴的顶部和底部。我们在同一图表中显示多个 Y 轴,它们之间有一些填充,每个轴可能都有自己的绘图带。我不希望这些溢出到另一个轴上,因为它们看起来像较小的单个图表。我还更改了悬停格式化程序,以便在将波段内的点悬停在绘图带上时显示这些绘图带的工具提示。

我遇到的问题是,如果您单击、拖动以缩放绘图带将恢复到它们波段在整个图表中的状态。我编写了一些代码来删除它们并重新添加它们,但似乎我需要在 addPlotBand 函数上回调以在实际添加和渲染之前更改 SVG 数组。我尝试重新添加它然后尝试重新绘制它,但没有奏效。

有没有办法在添加新绘图带时调整 SVG 元素,以便我可以更改 SVG 元素?

编辑:

以下是更多信息。我尝试使用选择事件删除所有波段,然后调用重绘,这会调用自定义重绘事件来放回 SVG 值。这是它的外观(选择事件首先有点粗糙,但它有效):

    SelectChart: function (chart) {
    var plotBandData = new Array();
    for (var i = 0; i < chart.xAxis[0].plotLinesAndBands.length; i++) {
        var band = chart.xAxis[0].plotLinesAndBands[i].svgElem, path = band.d.split(' ');
        var plotBand = chart.xAxis[0].plotLinesAndBands[i];
        //get all the plot band info so we can recreate them after resize
        var pbd = {
            from: plotBand.options.from,
            to: plotBand.options.to,
            id: plotBand.options.id,
            bottom: plotBand.options.iMBottom,
            top: plotBand.options.iMTop,
            color: plotBand.options.color
        };
        plotBandData.push(pbd);
    }
    //delete all existing plot bands:
    for (var i = 0; i < plotBandData.length; i++) {
        chart.xAxis[0].removePlotBand(plotBandData[i].id);
    }
    for (var i = 0; i < plotBandData.length; i++) {
        //Add plotband back in
        chart.xAxis[0].addPlotBand({
            from: plotBandData[i].from,
            to: plotBandData[i].to,
            color: plotBandData[i].color,
            id: plotBandData[i].id,
            iMBottom: plotBandData[i].bottom,
            iMTop: plotBandData[i].top
        });
    }
},

然后我的重绘事件看起来像这样:

    RedrawChart: function (chart){
    //SVG Code:
    for (var i = 0; i < chart.xAxis[0].plotLinesAndBands.length; i++) {
        var band = chart.xAxis[0].plotLinesAndBands[i].svgElem, path = band.d.split(' ');
        var bottomString = chart.xAxis[0].plotLinesAndBands[i].options.iMBottom + '';
        var topString = chart.xAxis[0].plotLinesAndBands[i].options.iMTop + '';
        path[2] = bottomString;
        path[path.length - 1] = bottomString;
        /*JH: this is interesting, the second value for top is typically in the 8th spot in the array
            However, before it's rendered the two right most "L"s are removed shifting everything to the left.
            an example would be:
            After render:
            M 525 100 L 525 100 L 525 50 L 707 50 L 707 100
            Before render (which is the state it's in here):
            M 525 100 L 525 100 L 525 50 707 50 707 100
            So you can see that the 8th value after render which is second top is shifted over one space.
            The last value which is the second bottom is shifted over 2 spaces.
        */
        path[5] = topString;
        path[7] = topString;
        band.attr('d', path);
    }
},

我的 SVG 值在重绘结束时是正确的,但是,高度仍然会渲染到图表的整个高度。

编辑:

现在,如果我只放大缩放中可见的绘图带,则会拉伸到图表的整个高度。重置缩放后,所有其他绘图带的大小都正确。然后,如果我选择图表中没有波段的区域,然后单击缩小所有图表波段都是正确的。似乎与选择中只有可见的绘图带有关。

以下是有效的方法:

我创建了一个在 X-Axis afterSetExtremes() 方法之后触发的新方法(我想如果你在 y 轴上这样做,你会在那里触发它)。我基本上只是从上述两种方法中获取代码并将其全部粘贴在那里。下面是从 xAxis.afterSetExtremes() 事件触发的代码:

    AfterChartSetExteremes: function (xAxis) {
    var plotBandData = new Array();
    for (var i = 0; i < xAxis.plotLinesAndBands.length; i++) {
        //get all the plot band info so we can recreate them after resize
        var plotBand = xAxis.plotLinesAndBands[i];
        var pbd = {
            from: plotBand.options.from,
            to: plotBand.options.to,
            id: plotBand.options.id,
            bottom: plotBand.options.iMBottom,
            top: plotBand.options.iMTop,
            color: plotBand.options.color
        };
        plotBandData.push(pbd);
    }
    //delete all existing plot bands:
    for (var x = 0; x < plotBandData.length; x++) {
        xAxis.removePlotBand(plotBandData[x].id);
    }
    for (var y = 0; y < plotBandData.length; y++) {
        //Add plotband back in
        xAxis.addPlotBand({
            from: plotBandData[y].from,
            to: plotBandData[y].to,
            color: plotBandData[y].color,
            id: plotBandData[y].id,
            iMBottom: plotBandData[y].bottom,
            iMTop: plotBandData[y].top
        });
    }
    $.each(xAxis.plotLinesAndBands, function (i, pband) {
        if (this.svgElem !== undefined) {
            var band = this.svgElem;
            path = band.d.split(' ');
            var bottomString = this.options.iMBottom + '';
            var topString = this.options.iMTop + '';
            path[2] = bottomString;
            path[path.length - 1] = bottomString;
            /*JH: this is interesting, the second value for top is typically in the 8th spot in the array
                However, before it's rendered the two right most "L"s are removed shifting everything to the left.
                an example would be:
                After render:
                M 525 100 L 525 100 L 525 50 L 707 50 L 707 100
                Before render (which is the state it's in here):
                M 525 100 L 525 100 L 525 50 707 50 707 100
                So you can see that the 8th value after render which is second top is shifted over one space.
                The last value which is the second bottom is shifted over 2 spaces.
            */
            path[5] = topString;
            path[7] = topString;
            this.svgElem.attr('d', path);
        }
    });
    //Need to reset formatter here?
}

函数中的 xAxis 是来自 afterSetExtremes 事件的"this",所以我只是像这样传递它:

function() {return PureSense.Clifford.IM.Charting.AfterChartSetExteremes(this);}

那行得通。放大或重置缩放后,所有绘图带都会调整大小。实际上,我使用我最初文章中的方法一直浏览了 highcharts 代码。我看到 SVG 值确实设置正确并一直保持。不过,重绘之外发生了一些事情,但我无法抓住它。

我确实知道它会发生,因为如果您查看我的评论,"d"数组比页面上的 SVG 元素少两个项目(如果您使用 F12 开发工具查看它)。afterSetExtreme 事件在重绘后和缩放发生后触发。我认为在重绘期间写入这些值会导致它们在缩放完成时被覆盖。

希望这对其他人有帮助。