Javascript 同时有时间延迟
Javascript while with time delay
我的目标我想运行循环,在n ms
(例如:200ms)时间间隔内逐步递减一个全局变量。
提前致谢!
我已经尝试过的
我尝试使用 ascy await。但是结合 css transition i 运行 在一个无限循环中(In codepen.io)。但是在 SO 中,如果你一直按向上箭头,你会发现它开始时 运行 并不顺利。
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let decrementing = false;
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("accelerate");
actionHandler( number++ );
decrementing = false;
downLoop();
}
});
function actionHandler(num) {
procentage.innerHTML = num;
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
window.addEventListener('keyup', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("decelerate");
decrementing = true;
downLoop();
}
});
async function downLoop() {
if (! decrementing) {
return false
};
const timer = ms => new Promise(res => setTimeout(res, ms));
while (number > 1) {
// how to decrement ever 200ms???
actionHandler( number-- );
await timer(200)
}
}
#engine {
background-color:black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background:green;
height: 50px;
width:0%;
transition: width 0.2s;
text-align:center;
}
.procentage {
position:absolute;
top: 50%;
left: 50%;
transform: translate(0%,-50%);
color: white;
fon-weight: bold;
font-size:28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow Up</p>
从以上评论...
"Instead of incrementing each time the number
value push a new async timer function, set to 200 msec delay but not immediately triggered, into an array. Create an async generator from it and iterate over the latter via the for-await...of
statement where one could decrement number
again." – Peter Seliger
"@PeterSeliger Hi Peter! Thank you for your comment. Can you make a small example please?" – Maik Lowrey
这里是请求的演示。
function createWait(delay) {
return async function wait () {
let settle;
const promise = new Promise((resolve) => { settle = resolve;});
setTimeout(settle, delay, { delay, state: 'ok' });
return promise;
};
}
async function* getWaitIterables(list) {
let wait;
while (wait = list.shift()) {
yield wait();
}
}
// demo for ...
// - creating an async `wait` function
// or a list of such kind.
// - creating an async generator from
// a list of async `wait` functions.
// - iterating an async generator of
// async `wait` functions.
const waitingList = [ // const waitingList = [];
2000, // waitingList.push(createWait(2000));
1000, // waitingList.push(createWait(1000));
3000, // waitingList.push(createWait(3000));
].map(createWait); // - The OP of cause needs to push into.
let number = 3; // - The incremented `number` value e.g. ... 3.
(async () => {
for await (const { delay, state } of getWaitIterables(waitingList)) {
--number;
console.log({ number, delay, state });
}
})();
console.log('... running ...', { number });
.as-console-wrapper { min-height: 100%!important; top: 0; }
每当你制作动画时,你不应该依赖 setInterval
或 setTimeout
,因为这意味着你将更新“X 毫秒后的某处”,这通常会在屏幕重绘,因此会导致动画卡顿。
相反,您应该使用 RequestAnimationFrame,它会在每次重绘之前进行计算。所以如果你有一个帧率为 60 Hz 的监视器,这意味着你将每秒重绘 60 次。对于每次重绘,检查自上次更新以来是否经过了足够的时间(下面的shouldTriggerUpdate()
),然后检查是否应该更新数字。
我还添加了 class KeyHandler
来跟踪按下了哪些键。
我最后草率地添加了一个递减作为 if 语句的“else”。当你想要设置更多要按下的键时,你会在到达那里时想出一些办法。
您不应使用 KeyboardEvent.keyCode,而应使用 KeyboardEvent.code
。
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let speed = 200 // ms
let lastUpdated = 0; // ms
let animationId = 0; // use later on to pause the animation
class KeyHandler {
ArrowLeft = false
ArrowUp = false
ArrowRight = false
ArrowDown = false
#setKey(code, value) { // private method
if (typeof this[code] != undefined) {
this[code] = value;
}
}
set pressedKey(code) {
this.#setKey(code, true);
}
set releasedKey(code) {
this.#setKey(code, false);
}
}
let keyHandler = new KeyHandler();
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
keyHandler.pressedKey = e.code;
});
window.addEventListener('keyup', (e) => {
e.preventDefault();
keyHandler.releasedKey = e.code
});
function actionHandler(num) {
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
function shouldTriggerUpdate(timeInMillis) {
let difference = timeInMillis - lastUpdated;
return difference >= speed;
}
function planeAnimation() {
let timeInMillis = new Date().getTime();
if (shouldTriggerUpdate(timeInMillis)) {
lastUpdated = timeInMillis;
if (keyHandler.ArrowUp) {
actionHandler(++number)
} else if (number > 0) {
actionHandler(--number)
}
}
animationId = requestAnimationFrame(planeAnimation)
}
animationId = requestAnimationFrame(planeAnimation);
#engine {
background-color: black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background: green;
height: 50px;
width: 0%;
transition: width 0.2s;
text-align: center;
}
.procentage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(0%, -50%);
color: white;
fon-weight: bold;
font-size: 28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow up</p>
我的目标我想运行循环,在n ms
(例如:200ms)时间间隔内逐步递减一个全局变量。
提前致谢!
我已经尝试过的
我尝试使用 ascy await。但是结合 css transition i 运行 在一个无限循环中(In codepen.io)。但是在 SO 中,如果你一直按向上箭头,你会发现它开始时 运行 并不顺利。
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let decrementing = false;
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("accelerate");
actionHandler( number++ );
decrementing = false;
downLoop();
}
});
function actionHandler(num) {
procentage.innerHTML = num;
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
window.addEventListener('keyup', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("decelerate");
decrementing = true;
downLoop();
}
});
async function downLoop() {
if (! decrementing) {
return false
};
const timer = ms => new Promise(res => setTimeout(res, ms));
while (number > 1) {
// how to decrement ever 200ms???
actionHandler( number-- );
await timer(200)
}
}
#engine {
background-color:black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background:green;
height: 50px;
width:0%;
transition: width 0.2s;
text-align:center;
}
.procentage {
position:absolute;
top: 50%;
left: 50%;
transform: translate(0%,-50%);
color: white;
fon-weight: bold;
font-size:28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow Up</p>
从以上评论...
"Instead of incrementing each time the
number
value push a new async timer function, set to 200 msec delay but not immediately triggered, into an array. Create an async generator from it and iterate over the latter via thefor-await...of
statement where one could decrementnumber
again." – Peter Seliger"@PeterSeliger Hi Peter! Thank you for your comment. Can you make a small example please?" – Maik Lowrey
这里是请求的演示。
function createWait(delay) {
return async function wait () {
let settle;
const promise = new Promise((resolve) => { settle = resolve;});
setTimeout(settle, delay, { delay, state: 'ok' });
return promise;
};
}
async function* getWaitIterables(list) {
let wait;
while (wait = list.shift()) {
yield wait();
}
}
// demo for ...
// - creating an async `wait` function
// or a list of such kind.
// - creating an async generator from
// a list of async `wait` functions.
// - iterating an async generator of
// async `wait` functions.
const waitingList = [ // const waitingList = [];
2000, // waitingList.push(createWait(2000));
1000, // waitingList.push(createWait(1000));
3000, // waitingList.push(createWait(3000));
].map(createWait); // - The OP of cause needs to push into.
let number = 3; // - The incremented `number` value e.g. ... 3.
(async () => {
for await (const { delay, state } of getWaitIterables(waitingList)) {
--number;
console.log({ number, delay, state });
}
})();
console.log('... running ...', { number });
.as-console-wrapper { min-height: 100%!important; top: 0; }
每当你制作动画时,你不应该依赖 setInterval
或 setTimeout
,因为这意味着你将更新“X 毫秒后的某处”,这通常会在屏幕重绘,因此会导致动画卡顿。
相反,您应该使用 RequestAnimationFrame,它会在每次重绘之前进行计算。所以如果你有一个帧率为 60 Hz 的监视器,这意味着你将每秒重绘 60 次。对于每次重绘,检查自上次更新以来是否经过了足够的时间(下面的shouldTriggerUpdate()
),然后检查是否应该更新数字。
我还添加了 class KeyHandler
来跟踪按下了哪些键。
我最后草率地添加了一个递减作为 if 语句的“else”。当你想要设置更多要按下的键时,你会在到达那里时想出一些办法。
您不应使用 KeyboardEvent.keyCode,而应使用 KeyboardEvent.code
。
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let speed = 200 // ms
let lastUpdated = 0; // ms
let animationId = 0; // use later on to pause the animation
class KeyHandler {
ArrowLeft = false
ArrowUp = false
ArrowRight = false
ArrowDown = false
#setKey(code, value) { // private method
if (typeof this[code] != undefined) {
this[code] = value;
}
}
set pressedKey(code) {
this.#setKey(code, true);
}
set releasedKey(code) {
this.#setKey(code, false);
}
}
let keyHandler = new KeyHandler();
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
keyHandler.pressedKey = e.code;
});
window.addEventListener('keyup', (e) => {
e.preventDefault();
keyHandler.releasedKey = e.code
});
function actionHandler(num) {
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
function shouldTriggerUpdate(timeInMillis) {
let difference = timeInMillis - lastUpdated;
return difference >= speed;
}
function planeAnimation() {
let timeInMillis = new Date().getTime();
if (shouldTriggerUpdate(timeInMillis)) {
lastUpdated = timeInMillis;
if (keyHandler.ArrowUp) {
actionHandler(++number)
} else if (number > 0) {
actionHandler(--number)
}
}
animationId = requestAnimationFrame(planeAnimation)
}
animationId = requestAnimationFrame(planeAnimation);
#engine {
background-color: black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background: green;
height: 50px;
width: 0%;
transition: width 0.2s;
text-align: center;
}
.procentage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(0%, -50%);
color: white;
fon-weight: bold;
font-size: 28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow up</p>