change setInterval to requestAnimationFrame - vue.js

How do I change the following code? I did not know how to convert this code. Can anyone help me?
let timer = ref(30);
let interval = setInterval(() => {
if (timer.value === 0) {
clearInterval(interval)
alert('done')
} else {
timer.value--
}
}, 1000)

This should work the same way as your original code. Of course, you don't need to pass an interval since requestAnimationFrame will be timed to the screen refresh rate.
let timer = ref(30);
function mainLoop() {
if (timer.value === 0) {
alert('done')
} else {
timer.value--
}
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
First the function mainLoop is defined. Then, it is called through requestAnimationFrame at the end of the script to 'kickstart' the loop. The subsequent calls to requestAnimationFrame within the function are there to maintain it.

Related

undefined is not an object (evaluating 'fun.__callAsync') trying to use setTimeout in a component

I'm using React Native and Reanimated and I want an animation to play after 2 seconds.
When a user moves a card, the card should stay at it's new position for 2 seconds, and then move back to it's place.
This is what I have:
const panGesture = useAnimatedGestureHandler<PanGestureHandlerGestureEvent>({
onActive: event => {
translateX.value = event.translationX;
if (event.translationX <= 0) {
// disabling swiping from right to left
translateX.value = 0;
}
},
onEnd: event => {
const shouldStick = translateX.value >= TRANSLATE_X_THRESHOULD;
if (shouldStick) {
translateX.value = withTiming(120);
runOnJS(moveBack)(translateX);
} else {
translateX.value = withTiming(0);
}
},
});
I tried using setTimeOut to count 2 seconds, and then update translateX but I get this error:
undefined is not an object (evaluating 'fun.__callAsync')
This is moveBack function:
const moveBack = (translateX: Animated.SharedValue<number>) => {
console.log("TRANSLATEX: " + translateX);
setTimeout(() => {
translateX.value = 0;
}, 2000);
}
I don't even see the TRANSLATEX log, so I guess it won't even get there.
I can't really figure out what's the problem or how to word it so I can find a solution.
The solution was way easier than I thought.
I'm using Reanimated 2.2.0 and there is withDelay option to add to the animation and it works great.
This is what I added after translateX.value = withTiming(120); (instead of the runOnJs line):
translateX.value = withDelay(2000, withTiming(0));
So right after setting translateX to 120, it waits 2 seconds, and then setting the value back to 0.
when using runOnJS
const doSomething = () => {
...
} // declare arrow function before runOnJS
runOnJS(doSomething)(arg)
function doSomething(){
...
} // can declare normal function before/after runOnJS coz of hoisting

How to correctly use setInterval for multiple functions being called repeatedly in React Native

I am building a simple app in React Native that aims to flash different colors on the screen at certain time intervals. My implementation is as follows:
useEffect(() => {
var blinkOnValue;
var blinkOffValue;
function blinkOn() {
const colorAndWord = getRandomColor(colorArray);
setBackground(colorAndWord.color);
}
function blinkOff() {
setBackground('#F3F3F3');
}
if (strobeStart) {
if (on) {
blinkOnValue = setInterval(() => {
blinkOn();
setOn(false);
}, info.length * 1000);
} else {
blinkOffValue = setInterval(() => {
blinkOff();
setOn(true);
}, info.delay * 1000);
}
}
return () => {
on ? clearInterval(blinkOnValue) : clearInterval(blinkOffValue);
};
}, [colorArray, info.delay, info.length, on, strobeStart]);
The blinkOn function sets the background a certain color and the blinkOff function sets the background a default light gray-ish color. These functions should alternate back and forth, blinking on and off at different intervals. For example, if info.length is 2 and info.delay is 0.5, then the color should flash on for 2 seconds and then the screen should be light gray for 0.5 seconds and repeat. However, the duration of both of the blinkOn and blinkOff are happening for the same amount of time, no matter what the two values are. Sometimes it uses the value from info.length, and sometimes it uses the value from info.delay which is also quite strange.
I think it has something to do with components mounting and unmounting correctly but honestly I am quite lost. If anyone has any advice on how to make this code consistently work where it flashes appropriately I would really appreciate it.
Instead of trying to time your events just right, I suggest using a single timer and computing the blink state from the current system time.
var oldState = true;
function blink() {
var ms = new Date().getTime();
var t = ms % (info.delay + info.length);
var state = (t < info.length ? true : false);
if (state == oldState) return;
if (state) {
blinkOn();
}
else
{
blinkOff();
}
oldState = state;
}
Now set a short timer to check the time and update the blink state as needed:
setInterval( () => blink(), 100 );

Restart a countdown in Livewire with Alpine.js

I try to build a survey, where a countdown should show a modal each 10 seconds, when the user waits too long.
The countdown should be stopped while the modal is shown and it should be restarted when the "back to survey" button is clicked and also when a question is answered.
I tried it that way with the alpine object:
let Countdown = () => {
return {
open: false,
heart:'',
ccdown(time,hue)
{
time -= 1;
hue += 60;
if (time > 0) {
this.heart=setTimeout(this.ccdown, 500, time, hue);
console.log("time: "+ time);
console.log("hue: " + hue);
}
if(time == 0) {
console.log("done");
this.open = true;
}
}
}
}
This is how I call the function in the blade component:
<div x-data="Countdown()" x-init="ccdown(10,30)">
...
</div>
But it stops after the second time.
Could anybody show me the problem?
The problem is here:
setTimeout(this.ccdown, 500, time, hue);
setTimeout only accepts two arguments, the function, and the timeout. If you have to call the function using arguments, you should either use bind or create a new function. So either it should be:
setTimeout(() => {
this.ccdown(time, hue)
}, 500)
Or,
setTimeout(this.ccdown.bind(this, time, hue), 500)

start countdown without any events

I have this script for countdown I wanted it to start as soon as the page loads (ideally i wanted it to run continuously since it is repeating in intervals).
when I call any function such as [startCountdown()] or [ countdown.start($('#countdown_clock').val());] I keep getting the same error [Uncaught ReferenceError: countdown is not defined]
here is the whole function
window.onload = function mainCountdown() {
var countdown = Tock({
countdown: true,
interval: 250,
callback: function () {
// console.log(countdown.lap() / 1000);
$('#countdown_clock').val(countdown.msToTime(countdown.lap()));
// countdown.start($('#countdown_clock').val());
},
complete: function () {
// console.log('end');
// alert("Time's up!");
repeatCountdown();
console.log('alarm');
}
});
$('#startCountdown').on('click', function () {
countdown.start($('#countdown_clock').val());
});
$('#pauseCountdown').on('click', function () {
countdown.pause();
});
$('#stopCountdown').on('click', function () {
countdown.stop();
});
$('#resetCountdown').on('click', function () {
countdown.stop();
$('#countdown_clock').val('00:10');
});
function repeatCountdown() {
countdown.stop();
$('#countdown_clock').val('00:10');
countdown.start($('#countdown_clock').val());
}
function startCountdown(){
countdown.start($('#countdown_clock').val());
}
}
How can I start the countdown without any button events.
Thank you in advance
You seem to have a few syntax issues that might be causing the problem. First, I'd call the window load event like this:
$(window).load(function () {
// functions, etc here
});
Then, inside the window load event, you can create your timer like this:
var countdown = new Tock(...
You were missing the 'var' and 'new' keywords. You might want to revisit the Tock documentation to make sure everything else was correct, too.

createjs newbie issue - changing score on event

I'm trying to decrease score of my hero on event. Specifically, when she misses her score decreases.
I've tried putting the event in the tick function and outside the tick function but both continue to decrement the score continuously.
function reducePower()
{
princessPower -= 1;
text.text = "Princess Power: " + princessPower;
gameStage.update();
}
Within the tick() function this code exists:
if(hitOrMiss == 'Miss')
{
reducePower();
//setTimeout(makeMada, 1);
}
The gameStage.update here causes the score to reduce constantly, I just want it to take one off every time the condition is met i.e. once when she misses - as in onChange. I see there is a createjs onchange function but when I try to use it, it fails for me, I'm probably using it wrong. The code is large so not saved it all but I've created a JSfiddle here: http://jsfiddle.net/3AJ48/
Any help appreciated.
Thanks,
I fixed this one myself. The score needed to be added outside the tick function as below for those who looked at the JSFiddle:
function onDeviceReady()
{
$("#image").rotate(
{
bind:
{
touchstart: function()
{
var rot = Math.floor ( Math.random() *24 ) *15;
value += rot;
$(this).rotate({ animateTo:value});
if(value % 2 === 0)
{
setTimeout(reduceMonsterPower, 2500);
setTimeout(hit,1000);
}
else
{
setTimeout(reducePower, 1500);
setTimeout(miss,1000);
}
}
}
});
}
function reducePower()
{
princessPower = princessPower - 20;
}
function reduceMonsterPower()
{
monsterPower = monsterPower - 40;
}