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.
Comments
Ben | 2 years ago
This looks like a really useful function! Looking forward to trying it
Want to leave a comment?
Comments are moderated. They will publish only if they add to the discussion in a constructive way. Please be polite.