Привет, я новичок с JavaScript и JQuery. То, что я пытаюсь сделать здесь, это напечатать текст, переданный в алфавите функции onclick() по алфавиту, используя функцию setTimeout. Я не уверен, что я делаю неправильно. Спасибо за вашу помощь.
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(), то параметры, такие как индекс, интервал, отображаются как неопределенные в предупреждающем сообщении? Почему это так?
Не используйте 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);
}
Рабочий jsfiddle с вашим HTML.
Изменить: Ой, забыл остановить цикл. Обновлена скрипка.
Редактировать 2: нашел опрятный трюк, который облегчает это с помощью 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]);
}
Смотрите, как он работает в этой скрипке. Трюк умножает delay
на index
(поэтому первый тайм-аут устанавливается на 0 * 500, второй - на 1 * 500, третий - на 2 * 500 и т.д.). Надеюсь, это также продемонстрирует прохождение параметров.
Проблема заключается в том 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);
}
Таким образом, вы снова установите интервал после первого запуска, а не "в одно и то же время". демонстрация
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);
}
}
Теперь что-то интересное:
Вместо setInterval
, если вы хотите контролировать общее время, которое происходит, чтобы сделать анимацию, которую вы можете использовать
.animate()
и эта функция step
:
> Живая демонстрация (3500 мс)
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]);
}
}
);
}
Прежде всего, начните с функции, которую вы вызываете с помощью setTimeout.
function (scrollTxt, interval, index, target) {
$('#myTxt').append(scrollTxt[index]);
}
Вы определили функцию с 4 параметрами, которые вызываются позднее. Проблема в том, что функция, заданная для setTimeout, не передает никакие параметры при ее вызове, поэтому внутри анонимной функции scrollTxt, интервал, индекс и цель будут неопределенными.
Чтобы преодолеть эту проблему, вы можете использовать закрытие. Внутри анонимной функции вы можете использовать переменные, доступные в области, определяющей анонимную функцию:
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
Примените это, и вы можете легко решить свою проблему (и понять, как вы ее решаете).
Не пытайтесь использовать атрибуты событий в 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
}
}
});
Рабочая скрипка
setTimeout
какsetTimeout(func, delay, param1, param2)
.