Customizing Vizzu Charts - Mouse-wheel zooming
Simon L谩szl贸
Posted on April 20, 2023
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.
Working example:
Posted on April 20, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.