Getting a new rndInt on each click

I want to be able to click on an image and have it rotate to a random number between 1080 and 1440 degrees. I have managed to achieve this but I want to be able to keep on clicking on the image and repeat this function over and over again, getting a new number each time.

import { timeline } from ‘wix-animations’
// ID: 7106D147D53400B9BB5AFFADBF985D6D

function randomIntFromInterval ( min , max ) { // min and max included
return Math . floor ( Math . random () * ( max - min + 1 ) + min )
}

const rndInt = randomIntFromInterval ( 1080 , 1440 )
console . log ( rndInt )

$w . onReady ( function () {

// Declare the two groups of page elements 
**const**  pink  =  $w ( '#image22' ) 

// Create the timeline 
// First hide the pink button, then rotate the white one 
**const**  tl  =  timeline () 
    . add ( pink , {  duration :  1000 ,  rotate :  rndInt  }) 

// On click replay the timeline from the beginning 
pink . onClick (() =>  tl . replay ()) 

});

Currently, my code will generate a random number and rotate the image but only use that one generated number without generating a new number on each click. Can somebody help?

This code will do what your code did, but repeat the spinning when the pic is clicked multiple times:

import { timeline } from 'wix-animations'

// ID: 7106D147D53400B9BB5AFFADBF985D6D

function randomIntFromInterval(min, max) { // min and max included 

    return Math.floor(Math.random() * (max - min + 1) + min)

}

$w.onReady(function () {

    // Declare the two groups of page elements

    const pink = $w('#image22')
    const tl = timeline()

    // Create the timeline

    // First hide the pink button, then rotate the white one

    // On click replay the timeline from the beginning

    pink.onClick(() => {
        const rndInt = randomIntFromInterval(1080, 1440)
        tl.add(pink, { duration: 1000, rotate: rndInt }).play()

    })

})

That being said, when doing rotate: number it rotates according to the spin it’s already had, so if the random number is 1400 the first time, then 1410 the second time, it will only rotate 10. If you want it to do the “big spin” every time you want this:

import { timeline } from 'wix-animations'

// ID: 7106D147D53400B9BB5AFFADBF985D6D

function randomIntFromInterval(min, max) { // min and max included 

    return Math.floor(Math.random() * (max - min + 1) + min)

}

$w.onReady(function () {

    // Declare the two groups of page elements

    const pink = $w('#image22')
    const tl = timeline()

    // Create the timeline

    // First hide the pink button, then rotate the white one

    // On click replay the timeline from the beginning

    pink.onClick(() => {
        const rndInt = randomIntFromInterval(1080, 1440)
        tl.add(pink, { duration: 1000, rotate: "+=" + rndInt }).play()

    })

})

That works brilliantly! Thank you very much for your help.

Is there any functionality to have the speed of spinning slow down as it reaches its intended goal? At the moment it spins at a consistent speed and stops on a random angle (which is perfect) but I think it would add to the experience if the spinning slowed as it got to the end.

@luke_semple In addition to duration and rotate add easing. Here is a nice vizualisation to the different ones: https://easings.net/

@simen Thank you for the link, it is a really interesting website. I have chosen the easing I would like but I am struggling to integrate it into my code.

For reference the easing I would like is easeOutCirc.

@luke_semple Should be as easy as changing

pink.onClick(() =>{ 
        let rndInt = randomIntFromInterval(1080, 1440)

        tl.add(pink, { duration: 1000, rotate: "+=" + rndInt}).play()
        
    })

into

pink.onClick(() =>{ 
        let rndInt = randomIntFromInterval(1080, 1440)

        tl.add(pink, { duration: 1000, rotate: "+=" + rndInt, easing:  "easeOutCirc"}).play()
        
    })

@simen You’re an absolute star, it works perfectly! Thank you very much for your help. You have saved a newbie a lot of time and pain.

@simen Hi Simen, sorry to be a pain but would you be able to advise if it would be possible to add a feature whereby depending on what angle the rndInt is, a textbox/image appears over the image with an explanation?

To explain further, currently my image spins to a random angle between 1080 - 1440 degress. If it landed between 1080-1100, I would like to display a unique message/image over the original spinning image. I would like to set individual messages/images for the entire range of angles.

Once the message has popped up, the user would click the unique message to make it disappear allowing them to re-spin the original image.

Here is an image for reference as to the image which is spinning.

Is this possible?

@luke_semple Yes, it’s possible. I’d first make a function that takes a number, then checks what range it falls within and returns the message/imageURL. Something like

function getImage(number){
    if(number < 1101){
    return "It was between 1080 and 1100"
    //for image you need to return the url for the image you want to display
    }
    if(number < 1121){
        return "It was between 1101 and 1120"
    }
    //and so on
}

Add a text field/image over the spinner, set it to hidden then add this to the onClick function

setInterval(() => {
    //for text:
    $w("#nameOfTextField").text = getImage(rndInt)
    //for image:
    $w("#nameOfImageField").url = getImage(rndInt)
}, 1010); //1010 because the duration of the animation is 1000

@luke_semple Ok, I realized I forgot some stuff. And that it’s easier to add things to the code than explain where every piece goes

import { timeline } from 'wix-animations'

// ID: 7106D147D53400B9BB5AFFADBF985D6D


function randomIntFromInterval(min, max) { // min and max included 

  return Math.floor(Math.random() * (max - min + 1) + min)

}

function getImage(number){
  if(number < 1101){
  return "It was between 1080 and 1100"
  //for image you need to return the url for the image you want to display
  }
  if(number < 1121){
      return "It was between 1101 and 1120"
  }
  //and so on
}





$w.onReady(function () {
  let spinnable = true;

    // Declare the two groups of page elements

    const pink = $w('#image22')


    // Create the timeline

    // First hide the pink button, then rotate the white one

    
    //When the image/text is clicked, the image/text is hidden and the user can spin again
    $w("#NameOfTheThingTheUserClicks").onClick(()=>{
      $w("#NameOfTheThingTheUserClicks").hide()
      spinnable = true
    })

    // On click replay the timeline from the beginning

    pink.onClick(() =>{ 
      if(!spinnable)
      return  //If a spin has happened and the user tries to spin again before clicking your image, it won't spin

        const tl = timeline()

        .add(pink, { duration: 1000, rotate: rndInt, easing:  "easeOutCirc"})
        let rndInt = randomIntFromInterval(1080, 1440)
        spinnable = false;
        
        setInterval(() => {
          //for text:
          $w("#NameOfTheThingTheUserClicks").text = getImage(rndInt)
          //for image:
          $w("#NameOfTheThingTheUserClicks").url = getImage(rndInt)

          $w("#NameOfTheThingTheUserClicks").show()

          
          
      }, 1010); //1010 because the duration of the animation is 1000
    })

});

I’ve marked the new bits in red so it’s easy to see what I’ve added. I haven’t tested it, but it should work.

@simen Hi Simen, I really appreciated the effort you are going to putting together this code for me. At the moment, I cannot get the wheel to spin at all.

When you refer to #NameOfTheThingTheUserClicks, do I have to create one of those links for every image I would like overlayed onto the top of the spinning wheel?

For reference, the spinning wheel is called #henwheel and the 2 overlays I have created for testing purposes are #weddingspeech and #heybaby.

Please could you take a look at the code and see where I have made a mistake?

import { timeline } from 'wix-animations'

// ID: 7106D147D53400B9BB5AFFADBF985D6D


function randomIntFromInterval(min, max) { // min and max included 

  return Math.floor(Math.random() * (max - min + 1) + min)

}

function getImage(number){
  if(number < 1101){
  return $w("#weddingspeech").url
  //for image you need to return the url for the image you want to display
  }
  if(number < 1441){
      return $w("#heybaby").url
  }
  //and so on
}


$w.onReady(function () {
  let spinnable = true;

    const pink = $w('#henwheel')

    
    //When the image/text is clicked, the image/text is hidden and the user can spin again
    $w("#weddingspeech").onClick(()=>{
      $w("#weddingspeech").hide()
      spinnable = true
    })

    pink.onClick(() =>{ 
      if(!spinnable)
      return  //If a spin has happened and the user tries to spin again before clicking your image, it won't spin

        const tl = timeline()

        .add(pink, { duration: 4000, rotate: rndInt, easing:  "easeOutCirc"})
        let rndInt = randomIntFromInterval(1080, 1440)
        spinnable = false;
        
        setInterval(() => {
          //for image:
          $w("#weddingspeech").url = getImage(rndInt)

          $w("#weddingspeech").show()

          
          
      }, 4010); //4010 because the duration of the animation is 1000
    })

});

I wouldn’t make one overlay per option, instead you add one image that you hide, then using the if statements to set the URL for the overlay, and then showing it.

This is to avoid having to add 18 overlays, so it’s not as cluttered in the editor (and possibly in the code). If you do want to go the mass overlay route I can probably write up some code for that.

But with all this back and forth, it might be easier with discord or something?

@simen In this instance, each segment of the wheel would require an individual overlay explaining what it means. Yes, we can move onto discord if you would like. My username is exSemplar#6923

Thank you again for your continued help.