Why the property in data doesnt update in setInterval - javascript

I want to create button to adjust/increase the props speed when my marker is moving, but in my case the speed work if the pause button clicked . what should i do if i want to click speed button and automatically update this.speed
I've declare speed prop in data and want to use in methods with setInterval
this is my data :
data: () => ({
speed: 1000
});
//my methods
moveMarker () {
this.mapLoop = setInterval(() => {
if (this.index + 1 === (this.coordinates.length)) {
this.isPlay = true
clearInterval(this.mapLoop)
new mapboxgl.Popup({ offset: 25 })
.setLngLat(this.newMarker._lngLat)
.setText('You are arrived')
.addTo(this.map)
}
const el = document.createElement('div')
el.className = 'marker'
console.log(el)
this.isPlay = false
this.map.panTo(this.coordinates[this.index])
const lat = this.coordinates[this.index][0]
const lng = this.coordinates[this.index][1]
this.newMarker.setLngLat([lat, lng])
this.newMarker.addTo(this.map)
this.index++
}, this.speed)
},
//trigger button function
forward () {
this.speed -= 500
},

You'll need to cancel the previous interval and re-start it with the new speed. For example
forward () {
clearInterval(this.mapLoop)
this.speed -= 500
this.moveMarker()
}

Related

react - using setInterval in a useCallback function that is called more than once

I'm trying to do the following
On isAnimate: boolean state change, determine if trigger animate() or draw()
draw() works fine
I also need a button to reset the animation, which is handled with the state toReset: boolean.
When toReset is true, immediately set toReset to false and call animate()
The animation is just an SVG with a single <path> element with its d attribute changed constantly.
Here are the functions that are of relevance (in source code writing order):
// Animation function (the problem function)
const animate = useCallback(() => {
console.log("animation start");
clearSVGPath(pathElement.current);
scaleSVGToPaths(svgElement.current, paths);
function* generatorPath() {
for (const path of paths) {
yield path;
}
}
const gen = generatorPath();
const animationTickTime = animationSpeed < 50 ? 1000 / animationSpeed : 20;
const animationTickPaths =
animationSpeed < 50 ? 1 : Math.round((20 * animationSpeed) / 1000);
console.log("tick time: ", animationTickTime);
console.log("tick lines: ", animationTickPaths);
clearInterval(animationIntervalID.current);
console.log("cleared animation interval ID: ", animationIntervalID.current);
function onTick() {
console.log("interval start");
let { value, done } = gen.next();
let i = 1;
const values = [];
while (i < animationTickPaths && !done) {
values.push(value);
({ value, done } = gen.next());
i += 1;
}
if (value) {
values.push(value);
}
console.log(values);
addPathsToSVG(pathElement.current, values);
if (done) {
clearInterval(animationIntervalID.current);
console.log("done");
}
}
console.log("starting interval");
animationIntervalID.current = setInterval(onTick, animationTickTime);
console.log("set: animation interval ID: ", animationIntervalID.current);
}, [animationSpeed, paths]);
// Draw Instantly
const draw = useCallback(() => {
clearSVGPath(pathElement.current);
scaleSVGToPaths(svgElement.current, paths);
setSVGPaths(pathElement.current, paths);
}, [paths]);
// reset animation
useEffect(() => {
if (!toReset) {
return;
}
setToReset(false);
animate();
return () => clearInterval(animationIntervalID.current);
}, [toReset, animate, setToReset]);
// Decide whether to draw instantly or animate
useEffect(() => {
if (!system) {
return;
}
if (!isAnimate) {
draw();
return;
}
animate();
return () => clearInterval(animationIntervalID.current);
}, [isAnimate, system, animate, draw]);
The problem: Upon change of isAnimate -> true (fourth codeblock, then first codeblock happens), it is all fine. However, upon toReset -> true, the animate() function is called but setInterval doesn't work correctly, even if cleared beforehand. Sometimes onTick() only runs one time before not working again, sometimes onTick() doesn't run at all.
A console screenshot after isAnimate -> true and then toReset -> true:
console screenshot
I'm not really sure what causes this problem, and would like assistance.
Thanks.

Javascript variable reference and/or copy

i have e video that i am scrolling with my mousewheel.
Everything is working fine but i would like to check if the user is still scrolling and if it is not so after 10 seconds i would like the video/scrollposition to set-back to zero.
The set-back is working but it is not happing after the "Interval". It is jumping back immediately.
This is my code so far:
const action = document.querySelector(".action");
const video = action.querySelector("video");
//Scroll Magic scenes
const controller = new ScrollMagic.Controller();
let scene = new ScrollMagic.Scene({
duration: 200000, //64000
triggerElement: action,
triggerHook: 0
})
.addIndicators()
.setPin(action)
.addTo(controller);
//Scroll Magic video animation
let accelAmount = 0.1;
let scrollpos = 0;
let currentTime = video.currentTime;
let lastcurrentTime;
let delay = 0;
scene.on("update", e => {
scrollpos = e.scrollPos / 3000; //the higher the number, the slower
});
//Move
setInterval(() => {
delay += (scrollpos - delay) * accelAmount;
video.currentTime = delay;
console.log(video.currentTime + " reading");
lastcurrentTime = video.currentTime;
}, 33.3);
//check if is still scrolling after x seconds
setInterval(checkTime, 10000);
//funktion to execute the check
function checkTime() {
console.log("waiting for new reading");
console.log(video.currentTime + " newreading");
currentTime = video.currentTime;
if (currentTime === lastcurrentTime) {
//is not scrolling -- go to start
//video.currentTime = 0;
window.scrollTo(0, 0);
}
}
You are updating the lastcurrentTime every 33.3ms and you're calling checkTime every 10s. So almost every time you call the checkTime, the lastcurrentTime will be synced with the video.currentTime.
I think that I would try something like this:
let setbackTimeout
scene.on("update", e => {
clearTimeout(setbackTimeout);
scrollpos = e.scrollPos / 3000; //the higher the number, the slower
setbackTimeout = setTimeout(checkTime, 10000);
});
every time you get an update you clear the countdown to setback and create another that you execute 10s later.
Listen to the scroll event listener. With a debounce-like function you can start a timeout that will run whenever the use stops scrolling.
The example below uses the aformentioned technique and shows a message whenever the user stops scrolling for 1 second.
function scrollTracker(delay, callback) {
let timeout = null;
return function(...args) {
if (timeout !== null) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(callback, delay, ...args)
};
}
const tracker = scrollTracker(1000, () => {
console.log('User stopped scrolling. Handle your video here');
});
window.addEventListener('scroll', tracker);
#page {
height: 20000px;
}
<div id="page"></div>
I think your concept is wrong. I made a little demo how to implement it. It will print the message after 4 sec "inactivity" on button.
const btn = document.querySelector("button")
let myInterval = setInterval(myPrint, 4000)
btn.addEventListener("click", () => {
clearInterval(myInterval)
myInterval = setInterval(myPrint, 4000)
})
function myPrint(){
clearInterval(myInterval)
console.log("programming <3")
}
<button>Click me!</button>

setInterval() and clearInterval() in React

Hello mighty people from internet,
I am trying to build a countdown timer app with pause and reset buttons using React hooks.
The timer countdown should stop once pause or reset button gets clicked performed by function pauseCountDown() and reset(), respectively.
However, the timer does not stop after pauseCountDown() or reset() executed.
I don’t quite understand why setInterval() does not stop after clearInterval() gets executed.
clearInterval() should be executed when isPaused === true.
However, the value of “isPaused” instantly switches back to false along with the next iteration of nonstopped setInterval().
Any ideas or thoughts what I missed or mistakes I have?
Thank you.
Here is the code of the child component performing timer countdown:
function TimerPanel(props) {
var launch;
var secLeft = parseInt(props.timerNow.min) * 60 + parseInt(props.timerNow.sec)
const startCountDown = () => {
props.setIsPaused(false)
launch = setInterval(decrement, 1000)
}
function decrement() {
if (secLeft > 0 && !props.isPaused) {
secLeft--;
var minCountDown = Math.floor(secLeft / 60)
var secCountDown = Math.floor((secLeft % 60) * 100) / 100
props.setTimerNow({...props.timerNow, min: minCountDown, sec: secCountDown})
}
}
const pauseCountDown = () => {
props.setIsPaused(true)
clearInterval(launch)
}
const reset = () => {
props.setIsPaused(false)
clearInterval(launch)
props.setSessionLength(props.initialTimer.min);
props.setTimerNow({...props.timerNow, min: props.initialTimer.min, sec: props.initialTimer.sec})
}
Since launch is just an ordinary variable, its value will not survive across rerenderings of TimerPanel. You'll need to store it inside a ref with useRef
// add useRef to your imports from react
import { useRef } from "react";
function TimerPanel(props) {
const launch = useRef();
var secLeft =
parseInt(props.timerNow.min) * 60 + parseInt(props.timerNow.sec);
const startCountDown = () => {
props.setIsPaused(false);
clearInterval(launch.current) // clean up any old timers
launch.current = setInterval(decrement, 1000);
};
function decrement() {
if (secLeft > 0 && !props.isPaused) {
secLeft--;
var minCountDown = Math.floor(secLeft / 60);
var secCountDown = Math.floor((secLeft % 60) * 100) / 100;
props.setTimerNow({
...props.timerNow,
min: minCountDown,
sec: secCountDown,
});
}
}
const pauseCountDown = () => {
props.setIsPaused(true);
clearInterval(launch.current);
};
const reset = () => {
props.setIsPaused(false);
clearInterval(launch.current);
props.setSessionLength(props.initialTimer.min);
props.setTimerNow({
...props.timerNow,
min: props.initialTimer.min,
sec: props.initialTimer.sec,
});
};
// ...
}

Why is the current time of the animation always 0?

I press one of the forw or back-buttons and then the run button, so the image goes in one of those directions, but when i try to log the currentTime, it just says 0 both times, why?...
forw.onclick = ()=>{
x = 630;
}
back.onclick = ()=>{
x = -630;
}
run.onclick = ()=>{
let animasjon = imgCar.animate([{
transform: `translateX(0px)`
},{
transform: `translateX(${x}px)`
}],{
duration: 1000,
fill: "forwards"
})
let cur = animasjon.currentTime
setInterval(() => {
console.log(cur)
}, 1200);
}
You are instantiating the variable once, and it just logs that same value each time your interval is called. If you want it updated, you need to update it in the interval like:
setInterval(() => {
cur = animasjon.currentTime
console.log(cur)
}, 1200);

how to make cocos creator touch listener

I started to learn cocos a few days ago and I don't really understand how to use the eventListener, I tried to copy the example code in their documentation website and make it so that instead of moving with the WASD keys you'll move by touching the screen, I tried to add it to the code but it didn't work... this is my code
cc.Class({
extends: cc.Component,
properties: {
// foo: {
// // ATTRIBUTES:
// default: null, // The default value will be used only
when the component attaching
// // to a node for the first time
// type: cc.SpriteFrame, // optional, default is typeof default
// serializable: true, // optional, default is true
// },
// bar: {
// get () {
// return this._bar;
// },
// set (value) {
// this._bar = value;
// }
// },
},
// Player.js
//...
properties: {
// main character's jump height
jumpHeight: 0,
// main character's jump duration
jumpDuration: 0,
// maximal movement speed
maxMoveSpeed: 0,
// acceleration
accel: 0,
},
//...
setJumpAction: function jump() {
// jump up
var jumpUp = cc.moveBy(this.jumpDuration, cc.p(0,
this.jumpHeight)).easing(cc.easeCubicActionOut());
// jump down
var jumpDown = cc.moveBy(this.jumpDuration, cc.p(0, -
this.jumpHeight)).easing(cc.easeCubicActionIn());
// repeat
return cc.sequence(jumpUp, jumpDown);
},
setInputControl: function () {
var self = this;
// add keyboard event listener
// When there is a key being pressed down, judge if it's the
designated directional button and set up acceleration in the corresponding
direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function
(event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = true;
break;
case cc.KEY.d:
self.accRight = true;
break;
case cc.KEY.w:
self.accUp = true;
break;
}
});
// when releasing the button, stop acceleration in this direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, function (event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = false;
break;
case cc.KEY.d:
self.accRight = false;
break;
case cc.KEY.w:
self.accUp = false;
break;
}
});
},
setTouchControl: function () {
//Create a "one by one" touch event listener (processes one touch at a time)
var listener1 = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
// When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
swallowTouches: true,
//onTouchBegan event callback function
onTouchBegan: function (touch, event) {
var x = touch.getLocationX();
var y = touch.getLocationY();
},
//Trigger when moving touch
onTouchMoved: function (touch, event) {
//Move the position of current button sprite
var x = touch.getLocationX();
var y = touch.getLocationY();
},
//Process the touch end event
onTouchEnded: function (touch, event) {
var x = touch.getLocationX();
var y = touch.getLocationY();
}
});
cc.systemEvent.addListener(listener1, this.node);
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, function (event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = false;
break;
case cc.KEY.d:
self.accRight = false;
break;
case cc.KEY.w:
self.accUp = false;
break;
}
});
},
// Player.js
onLoad: function () {
// initialize jump action
this.jumpAction = this.setJumpAction();
this.node.runAction(this.jumpAction);
// switch of acceleration direction
this.accLeft = false;
this.accRight = false;
this.accUp = false;
// current horizontal speed of main character
this.xSpeed = 0;
this.ySpeed = 0;
// initialize keyboard input listener
this.setInputControl();
this.setTouchControl();
},
// LIFE-CYCLE CALLBACKS:
// onLoad () {},
start() {
},
// update (dt) {},
// Player.js
update: function (dt) {
// update speed of each frame according to the current acceleration direction
if (this.accLeft) {
this.xSpeed -= this.accel * dt;
} else if (this.accRight) {
this.xSpeed += this.accel * dt;
}
// restrict the movement speed of the main character to the maximum movement speed
if (Math.abs(this.xSpeed) > this.maxMoveSpeed) {
// if speed reaches its limit, use the max speed with current direction
this.xSpeed = this.maxMoveSpeed * this.xSpeed / Math.abs(this.xSpeed);
}
// update the position of the main character according to the current speed
this.node.x = this.x;
},
});
I tried to use the function setTouchControl for my porpuses but I don't even know if it's good and if so how to use it in code...
ok, I found the answer... here:
properties: {
},
onLoad () {
this.node.on('touchstart', function(){
}, this.node);
this.node.on('touchmove', function (event) {
var delta = event.touch.getDelta();
this.x += delta.x;
this.y += delta.y;
}, this.node);
this.node.on('touchend', function () {
}, this.node);
},

Categories