【问题标题】:Trying to make append text letter by letter试图逐个字母地追加文本
【发布时间】:2013-09-27 11:28:22
【问题描述】:

您好,我是 JavaScript 和 Jquery 的新手。我在这里要做的是使用 setTimeout 函数按字母顺序打印在 onclick() 函数中传递的文本。我不确定我做错了什么。感谢您的帮助。

HTML

<div>
         <p id='myTxt'></p>
</div>
 <input type='button' value='Submit' onclick="imScrolling('Hello World!!', 500, 0, document.getElementById('myTxt'))">   

我的 Script.js 文件

 function imScrolling(scrollTxt, interval, index, target)
    {
        //alert(scrollTxt + " " + interval + " " + scrollTxt.length + " " + index + " " + target.id);
       while(index < scrollTxt.length)
      {
         //alert(scrollTxt[index]);
         setTimeout(function (scrollTxt, interval, index, target)
                {
                   $('#myTxt').append(scrollTxt[index]);
                   }, interval);
         index++;       
       }
    }

另外,我注意到如果我不将参数传递给 setTimeout(),那么像 index、interval 这样的参数在警报消息中显示为未定义?为什么会这样?

【问题讨论】:

  • 逐字还是逐字?您的标题与您在问题中要求的完全不同......
  • 谢谢罗科。刚刚改变了!

标签: javascript jquery settimeout


【解决方案1】:

问题是setTimeout 是异步的,但您的函数会保持同步运行while,因此setTimeout 会立即设置很多次。这是我的建议:

function imScrolling(scrollTxt, interval, index, target)
{
   setTimeout(function (){
       $('#myTxt').append(scrollTxt[index]);
       if(index < scrollTxt.length){
        imScrolling(scrollTxt, interval, index+1, target);
       }
       }, interval);
}

这样,您将在第一个触发后再次设置间隔,而不是“同时”。 Demo

【讨论】:

  • 谢谢哥们。我只是试了一下,但对我来说不太奏效。你能分享一个jsfile链接吗?例如如果我在 setTimeout 中添加带有参数的警报,则不会发生任何事情。
  • 对不起,我忘了删除'setTimeout'里面的函数参数。该函数不应该有参数。我编辑了答案,这是演示:jsbin.com/ohONuDe/1/edit?html,js,output
【解决方案2】:

不要使用setTimeout。你要的是setInterval

function imScrolling(scrollTxt, interval, index, target) {
    //alert(scrollTxt + " " + interval + " " + scrollTxt.length + " " + index + " " + target.id);

    var notawhileloop = setInterval(function () {
        //alert(scrollTxt[index]);
        $('#myTxt').append(scrollTxt[index]);
        index++;
        if (index == scrollTxt.length) {
            clearInterval(notawhileloop);
        }
    }, interval);
}

Working jsfiddle with your HTML.

编辑:糟糕,忘记停止循环了。也更新了小提琴。


编辑 2: 找到 a neat trick,这使得使用 setTimeout 也可以轻松完成此操作。

function imScrolling(scrollTxt, delay, index, target) {
    while (index < scrollTxt.length) {
        setTimeout(appendLetter, index * delay, scrollTxt, index);
        index++;
    }
}
function appendLetter(scrollTxt, index) {
    $('#myTxt').append(scrollTxt[index]);
}

See it working in this fiddle。诀窍是将delay 乘以index(因此第一个超时设置为 0*500,第二个超时设置为 1*500,第三个超时设置为 2*500 等)。希望这也能演示参数的传递。

【讨论】:

  • 谢谢贾斯汀一个简短的问题。你能告诉我,当我使用 setTimeout 函数时,为什么函数内部不能访问参数?警报将通知视为未定义。
  • @NarenSingh 好的,我不确定我是否完全理解您的问题,但参数不应传递给匿名函数,它们应该像 setTimeout(func, delay, param1, param2) 一样传递给 setTimeout
  • @NarenSingh 我用显示参数传递的setTimeout 版本更新了答案。
【解决方案3】:

尽量不要在 HTML 上使用事件属性。

jQuery 可以帮助你。

试试:

HTML

<div id="container">
    <p id="myTxt"></p>
    <input type="button" value="Submit" id="your-button" /> 
</div>

JAVASCRIPT

$(function () // jquery dom ready
{
    $("#container")
        .on("click", "#your-button", function ()
        {
            var yourText = "Hello World!!".split('');

            for (var i = 0; i < yourText.length; i++)
            {
                $("#myTxt")
                    .append(yourText[i])
                    .append("<br/>"); // just to line break
            }
        }
});

工作fiddle

【讨论】:

  • 谢谢哥们。这是另一个不错的选择!
【解决方案4】:

首先让我们从使用 setTimeout 调用的函数开始。

function (scrollTxt, interval, index, target) {
  $('#myTxt').append(scrollTxt[index]);
}

您已经定义了一个具有 4 个参数的函数,该函数稍后会被调用。问题是给 setTimeout 的函数在调用时没有传递任何参数,所以在匿名函数 scrollTxt 内部,interval、index 和 target 将是未定义的。

要解决此问题,您可以使用闭包。在匿名函数内部,您可以使用定义匿名函数的范围内可用的变量:

 var a = 5;
 function () {
    console.log(a); // 5
 }

还有一个问题。使用的变量是实际变量,而不是副本。所以如果你在外面改变变量,匿名函数里面的值也会改变:

var a = 5;
var f = function () {
  console.log(a);
}
a = 10;
f(); // outputs 10

为你改变的变量是索引。为了克服这个问题,您需要为每次迭代创建它的副本。有什么比将其作为参数提供给函数更好的方法呢?

for (var i=0; i<10; i++) {
  setTimeout((function(new_i) {
     return function () {
       console.log(new_i);
     };
  })(i),100);
}
// outputs 0,1,2,3,4,5,6,7,8,9

应用此方法,您可以轻松解决您的问题(并了解您是如何解决的)。

【讨论】:

  • 谢谢。这很有帮助。
  • 嗨 Tobos,你能看看我上面所做的编辑吗?该代码对我完全不起作用。再次感谢!
【解决方案5】:

> Live demo

function imScrolling(txt, intv, i, elID){

  var $el = $(elID),
      tot = txt.length,
      interv = setInterval(doIt, intv);   

  function doIt(){
    $el.append(txt[i++]);
    if(i==tot) clearInterval(interv);
  }
  
}

现在有趣的事情:

如何使用jQuery的动画方法:

如果您想控制执行动画的总时间而不是 setInterval,您可以使用
.animate(),它是 step > 功能:

> Live demo (3500ms)

function imScrolling(txt, time, i, elID){
  
    $({c:i}).animate(
      {c:txt.length},{
       duration : time,
       easing : 'linear',
       step : function(now){
           d = ~~(now);
           r = ~~(this.c);
           if(d!==r)$(elID).append(txt[r]);
       }
      }
    );     
  
}

【讨论】:

  • 感谢这让它变得简单了很多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
相关资源
最近更新 更多