Animation with Highcharts to Create a Lottery Wheel

Animation with Highcharts to create a lottery wheel

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:

  1. Create the Chart
  2. Rotate the animation
  3. Select the winner
  4. Spring the animation
  5. 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 🙂