0

嗨,我是 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 这样的参数在警报消息中显示为未定义?为什么会这样?

4

5 回答 5

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);
}

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

于 2013-09-26T14:33:16.580 回答
0

Don't use setTimeout. What you want is 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.

Edit: Oops, forgot to stop the looping. Updated fiddle as well.


Edit 2: Found a neat trick that makes it easy to do this with setTimeout as well.

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. The trick is multiplying the delay by index (so first timeout is set at 0*500, second at 1*500, third at 2*500 etc). Hope this also demonstrates the passing of parameters.

于 2013-09-26T14:43:58.157 回答
0

> 现场演示

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功能:

> 现场演示(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]);
       }
      }
    );     
  
}
于 2013-09-26T15:02:15.390 回答
0

尽量不要在 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
            }
        }
});

工作小提琴

于 2013-09-26T14:34:14.403 回答
0

首先,让我们从使用 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

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

于 2013-09-26T14:34:26.910 回答