In this tutorial, we will show you how to build a lottery wheel with Highcharts. This is possible thanks to the highly customizable library capability, you can create almost any interactive SVG-based visualization such as an interactive puzzle or a snake game.
The chart below displays a lottery wheel and the four setting options:
Let’s check the code, and understand how to create such a demo.
There four main parts to the code:
- Create the Chart
- Rotate the animation
- Select the winner
- Spring the animation
- Select the winner from the spring animation
Create the Chart
The first step is to create the wheel with the arrow.
The wheel code is simple and straightforward; it is just a basic pie chart:
chart = Highcharts.chart('container', { chart: { animation: false, marginTop: 100, events: { ... }, title: { text: 'Chance wheel' }, series: [{ type: 'pie', size: '100%', dataLabels: { distance: -20 }, data: [ ['Pudding', 1], ['Cake', 1], ['Salad', 1], ['Potato', 1], ['Bread', 1] ], startAngle: 360 * Math.random() }] });
The arrow is not provided out of the box using Highcharts, so you have to build it from scratch. Thanks to the renderer method, you can easily add any customized path to Highcharts code.
triangle = chart.renderer.path([ ['M', chart.chartWidth / 2 - 10, chart.plotTop - 5], ['L', chart.chartWidth / 2 + 10, chart.plotTop - 5], ['L', chart.chartWidth / 2, chart.plotTop + 10], ['Z'] ]) .attr({ fill: 'black' }) .add();
Once this part is done, it is time to move onto the animation part.
Rotate the animation
For the rotation animation, there are two main parts:
- Event handler
- Chart update
The main event will come from a click on the Spin button, which will trigger the animation button.addEventListener('click', e => {....
The animation has the update chart method to render the chart according to the new processed angles. The update chart method is called in the setInterval function for each iteration, and this is what makes the rotation effect:
// Create the arrow at the top. t = setInterval(() => { // Animation loop if (!physics.isActive) { startAngle += diff; if (startAngle > 360) { startAngle -= 360; } diff *= 0.98; chart.series[0].update({ startAngle });
The wheel’s speed will diminish after each rotation thanks to the diff variable that is used in this clever formula diff *= 0.98;
Now, the wheel is able to rotate and stop. Let’s see how to select a winner.
Select the winner
Once the wheel ceases movement, the findWinner
method below goes through the data set or slices and processes if the arrow position is within the slice start angle and the threshold winThreshold
. If there is a match, the findWinner
returns the slice’s index to get the label and display the winner.
const findWinner = (data) => { const sliceSize = 360 / data.length; const winThreshold = 360 - sliceSize; let sliceBeginning; for (let i in data) { sliceBeginning = radToDeg(data[i].shapeArgs.start) + 90; if (sliceBeginning > 360) { ... } } return -1; }
So far, the demo has all the lottery wheel components (see demo below):
However, we are not done yet. Let’s have some fun and add some fabricated physics movements 🙂
Spring the animation
The most important variables to create the fabricated physics movements are force, drag, current angle, target angle, strength, and threshold. Let’s gather them all under one object physics:
let physics = { force: 0, angleVel: 0, angle: 0, prevAngle: 0, // only used to calculate winner strength: 0.003 + strengthSlider.value / 10000, // tweakable drag: 0.98 + dragSlider.value / 1000, // tweakable threshold: 2 + lengthSlider.value / 10, // tweakable targ: 0, isActive: false };
Select the winner from the spring animation
The last step in this tutorial is to select the winner. As the wheel moves left and right, we read the temporary winner for each change of direction. The winner is definitely selected if the winner’s index is selected twice in a row (see code below):
if (physics.prevAngle >= physics.angle && currentWinner < 0) { currentWinner = findWinner(chart.series[0].data); foundPossibleWinner = true; } else if ( physics.prevAngle <= physics.angle && foundPossibleWinner ) { const nextWinner = findWinner(chart.series[0].data); if (currentWinner == nextWinner) { chart.setTitle({ text: 'The winner is ' + chart.series[0].data[currentWinner].name + '!' }); foundPossibleWinner = false; button.disabled = false; } else { currentWinner = -1; foundPossibleWinner = false; } }
Finally, our lottery wheel is ready to be used 🙂
Feel free to share your questions and comments in the comment section below. Don’t forget to let us know your experience with animation using Highcharts. Have fun with the wheel 🙂
Comments
Ben | 1 year ago
That is so cool! Can’t wait to try 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.