Customizing Vizzu Charts - Mouse-wheel zooming
Adding mouse-wheel zooming to a Vizzu chart in JavaScript can be useful for users who want to zoom in and out of a dense chart. In this how-to, we will create a Zoomer class that will handle the zooming functionality and then add event listeners to the Vizzu chart to connect the events to our Zoomer instance. And then, we will improve its performance by adding throttle to the zoom event calls.
Here are the steps to add mouse-wheel zooming over a Vizzu chart in JavaScript:
Step 1: Import Vizzu and data
First, we need to import the Vizzu library and an example data set as well, which we will visualize:
import Vizzu from 'https://cdn.jsdelivr.net/npm/vizzu@latest/dist/vizzu.min.js';
import { data } from 'https://lib.vizzuhq.com/0.7/assets/data/chart_types_eu.js'
Step 2: Create the chart
We can create the chart using the following code:
let chart = await (new Vizzu('vizzu-container', { data })).initializing;
This creates a new Vizzu chart instance with the provided data.
Step 3: Initialize the Chart with Zoom Range
Next, we create a line chart with an initial x-axis range.
chart.animate({
config: {
x: {
set: 'Year',
range: {
min: 0.5,
max: 20.5
}
},
y: 'Value 5 (+/-)',
geometry: 'line'
}
}, 0);
Now that we have a static chart, we can add the zoom functionality.
Step 4: Create the Zoomer class and instance
The Zoomer class will be used to track the zoom level of the chart:
class Zoomer {
constructor(min, max) {
this.min = min;
this.max = max;
this.finalMin = min;
this.finalMax = max;
this.pos = null;
}
trackPos(pos) {
this.pos = pos;
}
zoom(factor) {
let ref = this.min + this.pos * (this.max - this.min);
this.min = ref - (1 + factor) * (ref - this.min);
this.max = ref + (1 + factor) * (this.max - ref);
if (this.min < this.finalMin) this.min = this.finalMin;
if (this.max > this.finalMax) this.max = this.finalMax;
}
};
The constructor takes the initial minimum and maximum value of the x-axis range.
The trackPos
method is used to track the mouse position, and the zoom method is used to zoom in or out
based on the mouse wheel delta.
Now, we can create a new Zoomer instance with an initial zoom range of 0.5 to 20.5:
let zoomer = new Zoomer(0.5, 20.5);
Step 5: Add event listeners to the chart
We need to add event listeners to the chart to detect mouse-wheel and mouse-move events and prevent the default scroll event on the container element:
let container = document.getElementById('vizzu-container');
container.addEventListener('wheel', event => {
event.preventDefault();
})
chart.on('wheel', event => {
// Zoom event handling
});
chart.on('mousemove', event => {
// Mouse move event handling
});
Step 6: Handle the Zoom Event
When a zoom event is triggered, we update the zoom level using the Zoomer object and trigger an animation to update the chart with the new zoom range.
chart.on('wheel', event => {
zoomer.zoom(- event.data.delta / 200);
chart.animate(
{ x: { range: {
min: zoomer.min,
max: zoomer.max
} } },
{ duration: '50ms', easing: 'linear' });
});
Step 7: Handle the Mouse Move Event
When a mouse move event is triggered, we update the position of the Zoomer object to reflect the current mouse position.
chart.on('mousemove', event => {
zoomer.trackPos(event.data.coords.x);
});
With these steps in place, your Vizzu chart should now be able to handle mouse-wheel zooming events. However, you will notice that zooming events can be called before the chart animation can finish, delaying the zoom effect. To prevent this behavior, we will need to throttle the zoom call.
Step 8: Create the Throttle class
The Throttle class will be used to limit the number of zoom events that are processed at any given time.
class Throttle {
constructor() {
this.finished = true;
this.next = null;
}
call(func) {
if (!this.finished) {
this.next = func;
return;
}
else {
this.finished = false;
func().then(() => {
this.finished = true;
if (this.next !== null) {
let f = this.next;
this.next = null;
this.call(f);
}
})
}
}
}
let throttle = new Throttle();
The call method takes a promise-returning function as an argument and calls it if the promise returned by the previous function has resolved. Otherwise, it stores the function and waits for the current function’s promise to finish.
Step 9: Adding the throttle to the Zoom Event
We can now modify the zoom event to call the zoom method via our new throttle instance:
chart.on('wheel', event => {
zoomer.zoom(- event.data.delta / 200);
throttle.call(() =>
chart.animate(
{ x: { range: {
min: zoomer.min,
max: zoomer.max
} } },
{ duration: '50ms', easing: 'linear' })
);
});
With these additional steps, your Vizzu chart can handle mouse-wheel zooming events flawlessly.
Experience a live example by running this Pen! This example uses the same code provided in this article and allows you to see the zooming effect in action.
At Vizzu, we agree we could only make our tools better by building on your experiences and feedback. So drop us a line at hello@vizzuhq.com or join our Slack and share your stuff, ask for support, and be the part of our vibrant and growing community.
Thank you for choosing Vizzu!