Dynamically switch between linear and log axis scale using Stock Tools GUI

Dynamically switch between linear and log axis scale using Stock Tools GUI

In this article, I will show you how to add a custom logarithmic/linear Stock Tools button and how to interact with it. The custom stock tool button allows you to change the axes type from linear to logarithmic and the other way around.
Switching from logarithmic to linear scale can be useful with a particular set of data such as stock charts, as it allows be easier to interpret the chart using one of the scales.
Let’s begin with a simple chart where you can see how the charts’ appearance changes with different axis types. To demonstrate, I created an HTML button and I added an event listener to it.
When the button is clicked, we can use the axis update method to switch between the linear and logarithmic axis types. To track the changes I added the logarithmic flag.

let isLogarithmic = false;
document.getElementById('linlog').addEventListener('click', () => {
  chart.yAxis[0].update({
    type: isLogarithmic ? 'linear' : 'logarithmic'
  });
  isLogarithmic = !isLogarithmic;
});

Now let’s convert that knowledge into the Stock Tools GUI. As a starting point, we can cover that demo

The first step is to choose what kind of button to add to the GUI from the existing stackTools GUI buttons collection. Once your choice is made, select a name for the new one (lin/long switch), for this project, I named that button linLogSwitch and conveniently separated it from the other buttons by the separator.

The second step is to create the definition. Remember, that the definition name has to be the same as the button name to specify which button to add given styles and functionalities. I add to that definition a className and symbol that can be found in our library. The symbol shows the axis type which will be visible after clicking on that button.
If desired, you could use different symbols.
So far, the options looks like this:

stockTools: {
  gui: {
    buttons: ['linLogSwitch', 'separator', 'indicators', 'separator', 'simpleShapes', 'lines', 'crookedLines', 'measure', 'advanced', 'toggleAnnotations', 'separator', 'verticalLabels', 'flags', 'separator', 'zoomChange', 'fullScreen', 'typeChange', 'separator', 'currentPriceIndicator', 'saveChart'],
    definitions: {
      linLogSwitch: {
        className: ‘highcharts - lin - log -
          switch’,
        ,
        symbol: 'logarithmic.svg'
      },
    }
  }
},

A callback function is required to handle the button click event. This function must be named ‘init’. It will be defined in navigation.bindings (more here: navigation.bindings). With more complex buttons and their annotation, in some cases you might need to add other functions called start, steps and end. However, this isn’t necessary in this basic example.
The name of the property has to be (once again) the same as the button name to associate the right button. Inside it, based on the current chart state, I update the axis type using the axis update method.

When you click on the button and the scale is changed, the button’s icon is no longer valid because it shows the wrong axis type symbol. That is why you also need to update the button background image. Lastly, remove the default selection on the button.

navigation: {
  bindings: {
    linLogSwitch: {
      className: ‘highcharts - lin - log -
        switch’,
      init: function(button) {
        const chart = this.chart,
          isLogarithmic = chart.yAxis[0].logarithmic,
          axisTypeIcon = isLogarithmic ? 'logarithmic.svg' : 'linear.svg',
          iconURL = 'https://code.highcharts.com/9.2.2/gfx/stock-icons/' + axisTypeIcon;

        // Change the axis type accordingly.
        chart.yAxis[0].update({
          type: isLogarithmic ? 'linear' : 'logarithmic',
          minorTickInterval: isLogarithmic ? null : 'auto'
        }, false)
        chart.yAxis[1].update({
          type: isLogarithmic ? 'linear' : 'logarithmic',
          minorTickInterval: isLogarithmic ? null : 'auto'
        })

        // Change the button icon.
        button.firstChild.style['background-image'] = `url(${iconURL})`;

        // Deselect button after click.
        button.classList.remove('highcharts-active')
      }
    }
  }
},

In the end, here is the final demo:

Let me know your thoughts about this project, and feel free to share your experience in the comment section below.