我已经编写了一个简单的带后退间距的JavaScript / jQuery打字机,该打字机循环了几条消息(和背景图片)。

我面临的问题是,由于函数循环,它们没有正确写出-缺少几个字符。

即我的数组是[每个人,狗的主人,饮食意识强的工人,工人,家庭],但依次写成:ryone,g的主人,饮食意识强的(空白),家庭。

我认为问题可能出在某个地方的变量未正确重置或从上一条消息中计算出了长度-可能是作用域问题。

在Codepen上:https://codepen.io/nathankeenmelb/pen/MOovXJ?editors=0010

相关的HTML

<body>
  <div>
    <h2>There's something for<span id="message"> everyone.</span></h2>
  </div>
</body>


带有jQuery的JS

let messages = [
  " everyone.",
  " dog owners.",
  " the diet-conscious.",
  " workers.",
  " families."
];
let images = [
  "url(https://via.placeholder.com/200x100)",
  "url(https://via.placeholder.com/400x100)",
  "url(https://via.placeholder.com/400x200)",
  "url(https://via.placeholder.com/400x300)",
  "url(https://via.placeholder.com/400x400)"
];

let loopDuration = 3000;

function displayImages(arr){
  //Loop through other images, but start at second item
    let j = 1;
    setInterval( //evaluates every x ms
        function(){
            $('body').css("background-image",arr[j]);
            j++;
          console.log('j in image = ' + j);
          //Reset loop after been through them all to repeat
            if(j >= images.length) j = 0;
          //Interval length in ms
        }, loopDuration);
}

function displayMessages() {

  //CHANGE THE MESSAGE -starting the loop
    let i = 0;
    setInterval( //evaluates every x ms
        function(){
            //TYPEWRITE MESSAGE
            let char = 0;
            function typeWriter() {
              //for as long as the current character length is less than the full character length

              if (char < messages[i].length) {
                //Add the next character to the html
                document.getElementById("message").innerHTML += messages[i].charAt(char);

                //Go to next character
                char++;
                //Wait x ms to write next character
                setTimeout(typeWriter, 50);
              }

            } //end typewriter()

          //Run the function
          typeWriter();

          //START BACKSPACE
          let theMessage = document.getElementById("message").innerHTML;
          let bchar = theMessage.length;

          function backSpacer() {
            if (bchar > 0) {
              theMessage = theMessage.slice(0,-1);
              document.getElementById("message").innerHTML = theMessage;
              bchar--;
              //Run the function again, after x m
              setTimeout(backSpacer, 25);
            }
          }
          //Run the function
          backSpacer();

          //If instead of using backspacer() I deleted the text as follows, that worked fine
          //$('#message').text('');
          //document.getElementById("message").innerHTML = "";


          //Having typed it all out, backspaced it, go to the next message
          i++;

          //Having gone through each message, reset loop to repeat, to 0 to include the original
            if(i >= messages.length) i = 0;
          //Interval length in ms
        }, loopDuration);

}

//Wait till the whole page loads
window.onload = function loadChanges() {
  setTimeout(function() {
    //Run whatever after time elapses
    displayImages(images);
    displayMessages();
    //Wait x ms after page loads
  }, 1000)
};

最佳答案

我看了一下你的代码。在我看来,您同时运行typeWriterbackSpacer

您的代码具有以下结构(我已经对其进行了很多简化):

setInterval(function(){
  function typeWriter() {
    if (char < messages[i].length) {
      char++;
      setTimeout(typeWriter, 50);
    }

  }

  typeWriter();

  let bchar = theMessage.length;

  function backSpacer() {
    if (bchar > 0) {
      bchar--;
      setTimeout(backSpacer, 25);
    }
  }

  backSpacer();
}, loopDuration);


如您所见,您同时调用了typeWriter和backSpacer。 setTimeout将导致这些方法“并行”运行,因此同时删除和添加字母会导致消息混乱。

我创建了一个工作示例,该示例更多是状态机。这意味着它将首先键入该消息。完成后,它将切换为擦除消息。完成后,它将等待重新启动。

该代码虽然不好,但是它可以工作,并且可以帮助您获得有效的解决方案。如果您有任何疑问,请在评论中让我知道。

https://codepen.io/andreasmcdermott/pen/ZaXXyK?editors=0010

08-28 11:46