gpt4 book ai didi

javascript - setTimeout 内的 setTimeout 内的 setInterval

转载 作者:行者123 更新时间:2023-12-04 07:30:14 28 4
gpt4 key购买 nike

我正在尝试制作一个字符串,它会逐个字母地写出自己直到完成句子,并且每个字母出现的速度基于从 1 到 10 不等的输入。在字符串的末尾,它会闪烁5 秒,直到外星人出现。我的想法是创建一个 setInterval 来添加字母,当计数器添加数组大小时,它将使用新的 setInterval 调用返回循环的最终动画,在再次调用之前它已经被清除,并再次调用通过 setTimout 回调进行递归以保持无限循环。但它没有达到 setTimout,为什么?
//脚本.js

const speedInput = document.getElementsByClassName('speed--input')[0];
const alien = document.getElementsByClassName('alien')[0];
const textDiv = document.getElementsByClassName('text')[0];
const textShow = document.getElementsByClassName('text--show')[0];

const textDB = 'We go to dominate the world.';
const textStr = '';

let count = 0;
let speed = speedInput.value * 100;

const textChangeHandle = (count, textStr, textDB) => setInterval(() => {
if (count < textDB.length) {
textStr += textDB[count];
textShow.innerHTML = textStr;
textDiv.style.width = `${40 * count}px`;
count++;
} else {
textShow.style.animation = 'bip 1s linear 1s infinite'
return () => {
setTimeout(() => {
textShow.style.animation = '';
textStr = '';
count = 0;
textShow.style.opacity = 0;
alien.style.opacity = 1;

setTimeout(() => {
alien.style.opacity = 0;
textShow.style.opacity = 1;
textChangeHandle(count, textStr, textDB)
}, 5000)
}, 5000);
clearInterval(textChangeHandle);
}
}
}, speed)

textChangeHandle(count, textStr, textDB);
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style/style.css">

<title>Document</title>
</head>
<body>
<div class="text">
<p class="text--show"></p>
<img class="alien" src="alien.png" alt="Aki é Jupiter karai">
</div>

<div class="speed">
<span>Speed</span>
<input class="speed--input" type="number" min="1" max="10" value="1">
</div>

<script src="script.js"></script>
</body>
</html>
//样式.css
*,
*::after,
*::before {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}

body {
font-family: sans-serif;
background-color: #3cd070;
}

.text {
position: fixed;
top: 50%;
left: 50%;
height: auto;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
font-size: 40px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}

.text .alien {
opacity: 0;
height: 600px;
width: auto;
margin-bottom: 50px;
position: absolute;
}

.text .text--show {
font-size: 40px;
width: 100%;
position: absolute;
display: block;
text-align: center;
-webkit-animation: bip 1s linear 1s infinite;
animation: bip 1s linear 1s infinite;
}

.speed {
position: fixed;
top: 90%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.2);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 10px 20px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}

.speed .speed--input {
border: 0;
outline: 0;
width: 40px;
height: 25px;
margin: 10px;
text-align: center;
}

@-webkit-keyframes bip {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

@keyframes bip {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

最佳答案

还有animation frame api
它将在浏览器的下一次“自然”重绘之前运行您的函数。
此外,在您的情况下可能很有用,它会在您的回调中传递当前时间,因此您可以根据此获取时间详细信息并设置动画。这样,即使帧速率不一致,您也可以为每个人获得相同长度的流畅动画。
考虑以下代码段,它基本上会导致无限循环。

function draw(now) {
requestAnimationFrame(draw)
}

requestAnimationFrame(draw)
现在您只需要记住时间并在下次调用函数时取时间增量。如果时间足够长,您可以编写另一个字符。 (通常您会更改除以时间增量的值,但由于您有字符,它们要么存在,要么不存在。
let speed = 300
let timePassedSinceLastChar = 0
let then = null

function draw(now){
now *= 0.001;
const deltaTime = now - then;
then = now;
timePassedSinceLastChar += deltaTime;
if (timePassedSinceLastChar >= speed) {
drawChar()
timePassedSinceLastChar = 0
}
requestAnimationFrame(draw)
}

requestAnimationFrame(draw)
此外, requestAnimationFrame函数返回请求帧的 id。这允许取消循环。
const frameId = requestAnimationFrame(draw)
cancelAnimationFrame(frameId)
所以最终的代码可能看起来像这样。

const textDB = 'We go to dominate the world.';
let charIndex = 0;
let frameId = null
let then = 0
let sinceDraw = 0
let speed = () => Math.random() * 0.4 + 0.05 // randomize the speed a bit
let $p = document.querySelector('p')

function draw(now) {
// cancel on end of string
if (charIndex >= textDB.length) {
cancelAnimationFrame(frameId)
console.log('done')
return
}

// get the time delta
now *= 0.001; // convert to seconds
const deltaTime = now - then;
then = now;
sinceDraw += deltaTime

// if its time to draw again, do so
if (sinceDraw >= speed()) {
let char = textDB[charIndex]
$p.textContent += char
charIndex++
sinceDraw = 0
}
// request another frame
frameId = requestAnimationFrame(draw)
}

// request the first frame
frameId = requestAnimationFrame(draw)
<p></p>

关于javascript - setTimeout 内的 setTimeout 内的 setInterval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67978080/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com