基于 Highstock 中 rangeSelector 的选定范围的自定义刻度

custom ticks based on selected range from rangeSelector in Highstock

我试图让我的 Highcharts/Highstock 图表在 rangeSelector 设置为 All 时显示自定义刻度,我是这样设置的,但是当我尝试使用交互部分时却抛出错误图表

Received below answer from

  componentDidMount() {
    // Timezone Offset for PST standard is UTC timezone
    Highcharts.setOptions({
        global: {
          timezoneOffset: 8 * 60
        },
        lang: {
          thousandsSep: ','
        }
    });
    Highcharts.stockChart('chart', {
      chart: {
          backgroundColor:'rgba(255, 255, 255, 0.0)',
          height: 400,
          zoomType: 'xy'
      },

      title: {
          text: 'Bitcoin Chart',
          style: {
            color: 'white'
          }
      },

      navigator: {
        trigger: "navigator",
        triggerOp: "navigator-drag",
        rangeSelectorButton: undefined,
        handles: {
          backgroundColor: 'white',
          borderColor: 'black'
        }
      },

      scrollbar: {
        enabled: false
      },

      rangeSelector: {
        buttons: [{
            type: 'day',
            count: 1,
            text: '1d'
        }, {
            type: 'day',
            count: 7,
            text: '7d'
        }, {
            type: 'month',
            count: 1,
            text: '1m'
        }, {
            type: 'month',
            count: 3,
            text: '3m'
        }, {
            type: 'year',
            count: 1,
            text: '1y'
        }, {
            type: 'all',
            text: 'All'
        }],
          selected: 6,
          // styles for the buttons
          buttonTheme: {
            fill: 'black',
            // stroke: 'none',
            'stroke-width': 0,
            r: 8,
            style: {
                color: 'white',
                fontWeight: 'bold'
            },
            states: {
                hover: {
                },
                select: {
                    fill: 'white',
                    style: {
                        color: 'black'
                    }
                }
            }
          },
          // Date Selector box
          inputBoxBorderColor: 'black',
          inputBoxWidth: 120,
          inputBoxHeight: 18,
          inputStyle: {
              color: 'black',
              fontWeight: 'bold'
          },
          labelStyle: {
              color: 'silver',
              fontWeight: 'bold'
          },
      },

      series: [{
          name: 'Bitcoin Price',
          color: 'black',
          data: this.props.data.all_price_values,
          type: 'area',
          threshold: null,
          tooltip: {
            valuePrefix: '$',
            valueSuffix: ' USD',
            valueDecimals: 2
          }
      }],

      plotOptions: {
          series: {
              fillColor: {
                  linearGradient: [0, 0, 0, 0],
                  stops: [
                      [0, '#FF9900'],
                      [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
                  ]
              }
          }
      },

      xAxis: {
        events: {
          setExtremes: function(e) {
            if (e.trigger === "rangeSelectorButton" && e.rangeSelectorButton.text === "All") {
              var range = e.max - e.min;

              // ticks spaced by one day or one hour
              var ticksSpacing = range >= 86400 * 1000 ? 86400 : 3600;

              this.update({
                  tickPositioner: function() {
                      var positions = [],
                      info = this.tickPositions.info;
                      for (var x = this.dataMin; x <= this.dataMax; x += ticksSpacing * 1000) { // Seconds * 1000 for ticks
                          positions.push(x);
                      };
                      positions.info = info;
                      return positions;
                  }
              }, false);
            }
          }
        },
        title: {
          enabled: true,
          text: 'Date (Timezone: PST)',
          style: {
            color: 'white'
          }
        },
        labels: {
          style: {
            color: 'white'
          }
        },
        type: 'datetime',
        dateTimeLabelFormats: {
            day: '%b %e, %Y'
        },
        tickInterval: 1
      },

      yAxis: {
        floor: 0,
        labels: {
          formatter: function () {
                    return '$' + this.axis.defaultLabelFormatter.call(this);
            },
          format: '{value:,.0f}',
          align: 'left',
          style: {
            color: 'white'
          },
        },
      },
      // Mobile Design
      responsive: {
          rules: [{
              condition: {
                  maxWidth: 600
              },
              chartOptions: {
                  chart: {
                      height: 400
                  },
                  subtitle: {
                      text: null
                  },
                  navigator: {
                      enabled: false
                  }
              }
          }]
      }
    });
  }

我说的是蓝色突出显示的部分,当我移动它时,它会抛出错误

我试图让图表在所有范围选择器上每天有 2 个图,显示当天的第一个点和一天的最后一个点。我做错了什么?

编辑 1:更新为完整配置,X 轴现在被原始答案打乱,自定义范围选择器上的刻度仍在工作中。添加图像以显示正在发生的事情

每次更改要在图表上显示的范围时都会引发 setExtremes 事件。它可以有几个来源:

  • 在范围选择器中单击一个按钮
  • 导航器中的手柄拖动
  • 等..

事件的实际属性取决于它的起源。如果您使用 console.log(e) 输出事件,您会发现这两个来源并不相同:

单击范围选择器中的按钮

{
    trigger: "rangeSelectorButton",
    rangeSelectorButton: {
        text: "2Hour", 
        type: "hour",
        count: 2, 
    }, 
    ...
}

在导航器中处理拖动

{
    trigger: "navigator", 
    triggerOp: "navigator-drag", 
    rangeSelectorButton: undefined
}

如果您在导航器中拖动手柄,则不会 rangeSelectorButton 附加到事件,因为它没有意义:在这种情况下,不会按下任何按钮。

要修复您的错误,您可以在 trigger 属性:

上添加检查
 xAxis: {
    events: {
      setExtremes: function(e) {
        if (e.trigger === "rangeSelectorButton" && e.rangeSelectorButton.text === "All") {
           ...
        }
      }
   }

如何解决实际问题

现在,真正的问题。您想要根据显示的内容更改刻度:每天的开始和结束,或者小时(如果不是完整的一天)。您可以使用代表所选时间范围的 e.mine.max 来做到这一点。

像这样:

setExtremes: function(e) {
    var range = e.max - e.min;

    // ticks spaced by one day or one hour
    var ticksSpacing = range >= 86400 * 1000 ? 86400 : 3600;

    this.update({
        tickPositioner: function() {
            var positions = [],
            info = this.tickPositions.info;
            for (var x = this.dataMin; x <= this.dataMax; x += ticksSpacing * 1000) { // Seconds * 1000 for ticks
                positions.push(x);
            };
            positions.info = info;
            return positions;
        }
    }, false);
}