data.map((d, i) => {
setTimeout(() => {
drawCanvas(canvasRef, d);
}, 1000 * i);
});
i applied loop on array using map with a delay of one second now i want to add a pause or resume function on this loop. Is it possible to perform anything like this?or any other solution
CodePudding user response:
You can use async
/await
to "sleep" for a given duration; using a Promise
.
const sleep = async (ms) => new Promise(res => setTimeout(res, ms));
(async () => {
for (let i = 0; i < data.length; i ) {
await sleep(1000); // Sleep for 1 second between
drawCanvas(canvasRef, data[i]);
}
})();
Working example
const
sleep = async (ms) => new Promise(res => setTimeout(res, ms)),
canvasRef = { current: document.querySelector('#drawing') };
const drawCanvas = (canvasRef, conf) => {
const ctx = canvasRef.current.getContext('2d');
ctx.fillStyle = conf.color;
ctx.beginPath();
switch (conf.kind) {
case 'circle':
ctx.arc(conf.x, conf.y, conf.radius, 0, 2 * Math.PI);
break;
case 'rectangle':
ctx.fillRect(conf.x, conf.y, conf.width, conf.height);
break;
case 'triangle':
ctx.moveTo(conf.x, conf.y);
ctx.lineTo(conf.x, conf.y conf.height);
ctx.lineTo(conf.x conf.width, conf.y conf.height);
break;
}
ctx.closePath();
ctx.fill();
};
const data = [
{ kind: 'rectangle', x: 30, y: 40, width: 140, height: 30, color: 'blue' },
{ kind: 'rectangle', x: 80, y: 20, width: 50, height: 20, color: 'blue' },
{ kind: 'triangle', x: 130, y: 20, width: 20, height: 20, color: 'blue' },
{ kind: 'circle', x: 70, y: 70, radius: 16, color: 'red' },
{ kind: 'circle', x: 130, y: 70, radius: 16, color: 'red' },
];
Object.assign(canvasRef.current, { width: 200, height: 100 });
(async () => {
for (let i = 0; i < data.length; i ) {
await sleep(1000); // Sleep for 1 second between
drawCanvas(canvasRef, data[i]);
}
})();
#drawing { border: thin solid grey; }
<canvas id="drawing"></canvas>
CodePudding user response:
You can't pause a map
, because it's sync
in nature, modern JS has something called async / await
that makes doing this simply.
Pausing can be accomplished by using a Promise constructor that you can manually resolve based on some event, eg. checkbox click etc.
Below is a simple example that counts from one to ten in an infinite loop, that you can then pause / resume by checking the checkbox.
const numbers = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
const sleep = ms => new Promise(r => setTimeout(r,ms));
const elNum = document.querySelector('#num');
const elInput = document.querySelector('input');
let pause = Promise.resolve();
const pauseClick = cb =>
elInput.addEventListener('click', cb, {once: true});
function checkForPause() {
pauseClick(() => {
pause = new Promise(resolve => {
pauseClick(() => { resolve(); checkForPause();});
});
});
}
checkForPause();
async function run() {
while (true) {
for (const num of numbers) {
elNum.innerText = num;
await sleep(1000);
await pause;
}
}
}
run();
#num {
font-size: 20pt;
}
Pause: <input type="checkbox"/>
<div id="num">....</div>