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

时间:2018-03-09 07:15:29

标签: reactjs highcharts highstock

我试图让我的Highcharts / Highstock图表在rangeSelector设置为All时显示自定义刻度,我设置了这种方式,但是当我尝试使用图形的交互部分时,我会犯错误< / p>

  

Highstock Change tick interval on range selector change

收到以下回答
  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
                  }
              }
          }]
      }
    });
  }

enter image description here

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

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

编辑1:更新为完整配置,X轴正在被原始答案中断,自定义范围选择器上的刻度仍然有效。添加图片以显示正在进行的操作

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

每次更改要在图表上显示的范围时,都会引发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);
}