简体   繁体   中英

Change delay in setTimeout using a button click

I am working on creating a 3D rotating cube in HTML canvas. My code looks something like this

function rotateCubeZM() {
    fr = 5;
    stoppage = 1;   
    for(let i = 0;i<200;i++,fr+=dacc) {
        setTimeout(rotateCubeZ,i*fr*stoppage,1);
    }
}

Here dacc is a de-acceleration factor which slows down the rotation. I need to create button friction which will further slow down the de-acceleration by factor x. How do I change the de-acceleration factor while setTimeout is still in progress? I tried updating the value of dacc with an onclick function but that doesn't work. Or is there any other way to call the above function that can help in this?

Thanks for the help.

Do not use timers to change speed. The display rate of the device is fixed at 60 frames a second. You should animate in sync with this rate. Use requestAnimationFrame (rAF)

The code below uses rAF to update the animation once ever 60th second.

  • rotateSpeed is how much to rotate each frame
  • Each frame this speed is reduced by the amount in dacc . If below some min minSpeed the rotation is stopped;
  • A click event can change the rate of deceleration by changing dacc
  • rAF will stop when the rotate speed is below minSpeed.
  • To start the animation call startRotateAnim();

The values used are just an estimate of from your code. You will have to play with the values to get the animation to look how you want.

const fr = 5;  
const minSpeed = 0.01;
var rotateSpeed = 0, dacc;

// click event for quicker slowdown 
myButtonElement.addEventListener("click",() => dacc = 0.8);

// function to start / restart animation
function startRotateAnim() { 
    const animRunning = rotateSpeed > minSpeed; // if animation running just change values   
    rotateSpeed = 1 * (1000/60) / fr; // rotate per frame
    dacc = 0.4;        // the bigger the number the quicker the slowdown
    if (!animRunning) {
        requestAnimationFrame(mainLoop); // start the animation.
    }
}

function mainLoop() {  // this is called 60 times a second
    if (rotateSpeed > minSpeed) {  rotateSpeed -= dacc }
    if (rotateSpeed > minSpeed) { 
        rotateCubeZ(rotateSpeed);
        requestAnimationFrame(mainLoop);
    }
}

You can't do that. You have to clear the timeout and set a new timeout. setTimeout retuns a unique identifier.

// timer holds the timer identifier.
let timer = setTimeout(function, 1000);

// clear it when you click the button
clearTimeout(timer);

// and set new timer with new value
timer = setTimeout(function, 2000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM