使用setInterval错误更新了innerHTML

时间:2018-07-01 23:02:02

标签: javascript html

我正在尝试使用纯js创建基本的打字机。

我基本上是在尝试模仿人们以一种可信的方式使用键盘打字。问题是由于某种原因,我节点的文本似乎没有显示,而且我似乎也找不到原因

function get_random_in_interval(min, max){
   return Math.floor(Math.random() * (max - min + 1)) + min;
 }

function typewriter(textinput){
  var min = 1;
  var max = 3;
  var rand = get_random_in_interval(min, max);
  var into = document.getElementById('textentry');


  for (i = 0; i < textinput.length; i++){
        var timer = setInterval(function(){
        if (i >= textinput.length){
          clearInterval(timer);
        }

        into.innerHTML += textinput.charAt(i);
      }, rand * 1000);
  }

}


 var test = "Hello, I am a <b>text</b> \n \n I tried doing some freaky stuff";
 typewriter(test);
#textentry {
  border: 10px solid #2c3e50;
  width: 400px;
  height: 100px;
  background-color: #95a5a6;
  font-family: Consolas, monospace;
  color: #FFF;
}
<div id="textentry"></div>

我最好的猜测是我在这里错误地使用了setInterval()函数。问题是,我真的无法想到应该将其放置在其他位置。如果我将setInterval()放在for()循环之外,那么它将可以工作(自己进行测试),但是它将以随机的间隔打印整个字符串,而不仅仅是所需的char。

3 个答案:

答案 0 :(得分:2)

这是一个更简单的解决方案(与其他解决方案相比):

这基本上使用setInterval,然后在i超过长度后停止。

function get_random_in_interval(min, max){
   return Math.floor(Math.random() * (max - min + 1)) + min;
 }

function typewriter(textinput){
  var min = 1;
  var max = 3;
  var rand = get_random_in_interval(min, max);
  var into = document.getElementById('textentry');
  var i = 0;
  let Htmlstring = ""; // Credit to Certain Performance for the idea

  var timer = setInterval(function(){
    Htmlstring += textinput.charAt(i);
    into.innerHTML = Htmlstring;
    i++;
    if (i > textinput.length) {
      clearInterval(timer);
    }
  }, get_random_in_interval(min, max)*30);
  

}


 var test = "Hello, I am a <b>text</b> \n \nI tried doing some freaky stuff";
 typewriter(test);
#textentry {
  border: 10px solid #2c3e50;
  width: 400px;
  height: 100px;
  background-color: #95a5a6;
  font-family: Consolas, monospace;
  color: #FFF;
}
<pre id="textentry"></pre>

答案 1 :(得分:2)

这里有一些很好的答案。我将其发布为另一种替代方法,因为有很多方法可以做到这一点。您可以通过小型递归函数使用setTimeout代替setInterval

function get_random_in_interval(min, max){
    return Math.floor(Math.random() * (max - min + 1)) + min;
    }

function typewriter(textinput){
    const min = 60;
    const max = 120;
    const into = document.getElementById('textentry');
    const type = (i) => {
        let rand = get_random_in_interval(min, max);
        setTimeout(() => {
            into.innerHTML = textinput.slice(0,i++)
            if (i < textinput.length) type(i)
        }, rand)
    }
    type(0)
}

var test = "Hello, I am a <b>text</b> \n \n I tried doing some freaky stuff";
typewriter(test);
#textentry {
  border: 10px solid #2c3e50;
  width: 400px;
  height: 100px;
  background-color: #95a5a6;
  font-family: Consolas, monospace;
  color: #FFF;
}
<div id="textentry"></div>

答案 2 :(得分:1)

所有时间间隔均同步设置。到typewriter函数结束时(在运行任何间隔之前),i等于textinput.length,因此into.innerHTML += textinput.charAt(i);不起作用。

您还希望在每次迭代之前暂停-为此,在循环中awaitPromise可能最简单。 (您绝对不希望setInterval

const get_random_in_interval = (min, max) => (
  new Promise(res => setTimeout(res, Math.floor(Math.random() * (max - min + 1)) + min))
);

async function typewriter(textinput){
  var min = 5;
  var max = 45;
  var into = document.getElementById('textentry');
  let htmlStr = '';
  for (let i = 0; i < textinput.length; i++){
    await get_random_in_interval(min, max);
    htmlStr += textinput.charAt(i);
    into.innerHTML = htmlStr;
  }
}
 var test = "Hello, I am a <b>text</b> <br> <br> I tried doing some freaky stuff";
 typewriter(test);
#textentry {
  border: 10px solid #2c3e50;
  width: 400px;
  height: 100px;
  background-color: #95a5a6;
  font-family: Consolas, monospace;
  color: #FFF;
}
<div id="textentry"></div>

如果要键入HTML,请将\n替换为<br>