custom ticks based on selected range from rangeSelector in Highstock

扶醉桌前 提交于 2019-12-13 04:22:54

问题


I am trying to get my Highcharts/Highstock chart to display a custom tick when the rangeSelector is set to All, I have it setup this way, but is throwing me errors when I try to use the interactive portion of the graph

Received below answer from 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
                  }
              }
          }]
      }
    });
  }

I am talking about the blue highlighted section, when I move it, it throws an error

I am trying to get the charts to have 2 plots per day on ALL rangeSelector, displaying the first point in the day and the last point in a day. What am I doing wrong?

EDIT 1 : Updated to full config, X Axis is now being disrupted by the original answer, ticks on custom range selector is still in works. Added images to show what's going on


回答1:


The setExtremes event is raised each time you change the range to be displayed on the graph. It can have several origins:

  • A button click in the range selector
  • An handle drag in the navigator
  • etc..

The actual properties of the event depend on its origin. If you output the event with console.log(e), you'll see that it's not the same for these two origins:

Button click in the range selector

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

Handle drag in the navigator

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

If you drag the handle in the navigator, there's no rangeSelectorButton attached to the event, because it doesn't make sense: in that case, no button is pressed.

To fix your error, you can add a check on the trigger property:

 xAxis: {
    events: {
      setExtremes: function(e) {
        if (e.trigger === "rangeSelectorButton" && e.rangeSelectorButton.text === "All") {
           ...
        }
      }
   }

How to solved the actual issue

Now, the REAL issue. You want to change the ticks based on what is displayed: either the beginning and end of each day, or hours if not a complete day. You can do that with e.min and e.max, that represent the selected time range.

Like so:

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);
}


来源:https://stackoverflow.com/questions/49188433/custom-ticks-based-on-selected-range-from-rangeselector-in-highstock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!