我正在尝试创建一个函数 speak(),它递归地运行一个字符串数组,逐渐淡入和淡出每个字符串,然后进入下一个字符串。这是我的代码:
index
我遇到的问题是字符串淡入,切换到下一个字符串,然后淡出。我希望它淡入,淡出,然后切换到下一个字符串,而#maintext是不透明的。无论我尝试使用这个功能,我都无法弄清楚出了什么问题。
它打印每个字符串,转换只是在错误的位置。
JFiddle,虽然我根本无法让JFiddle工作(我想我可能把它格式化了)。 https://jsfiddle.net/t2q9jdsx/10/
答案 0 :(得分:3)
这应该对你有所帮助。我没有首先设置.text
,而是淡出元素,然后交换文本,然后将其淡入。当您运行下面的代码片段时,您会看到它有效。它使用提供给#maintext
元素的文本内容作为初始文本也非常方便。您还会看到最后一个字符串是在我们通过数组完成递归后仍然显示的字符串。
使用您的代码,#maintext
总是以fadeOut
结束,这意味着在显示所有字符串后,#maintext
将始终不可见。
const speak = ($elem, time, [x,...xs]) => {
if (x === undefined) return null;
$elem.fadeOut(time, () => {
$elem.text(x).fadeIn(time, () => {
speak($elem, time, xs)
})
})
}
let strings = ['foo', 'bar', 'baz', 'bof']
speak($('#maintext'), 1000, strings)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maintext">init</div>
如果您没有使用babel来转换JS,那么您可能需要使用pre-ES6版本。你去吧
function speak($elem, time, strings) {
if (strings[0] === undefined) return null;
$elem.fadeOut(time, function() {
$elem.text(x).fadeIn(time, function() {
speak($elem, time, strings.slice(1))
});
});
}
其他评论
您使用状态变量在正确的轨道上跟踪递归函数中的索引。但是,我通常发现更容易切掉数组的头部(第一个元素)并使用其余元素进行递归。为了向您展示您的方法同样可行,我将使用索引重新实现我的答案。
这里最大的区别是我们现在需要在函数中使用 4 变量(而不是3),并且我们需要在每次迭代时将索引与strings.length
进行比较。这不是一个大问题,但跟踪索引和不断检查数组length
的额外认知开销是我更喜欢我给出的第一个答案的形式/风格的原因。
function speak ($elem, time, strings, i) {
if (i >= strings.length) return;
$elem.fadeOut(time, function () {
$elem.text(strings[i]).fadeIn(time, function () {
speak($elem, time, strings, i + 1);
});
});
}
var strings = ['foo', 'bar', 'baz', 'bof'];
speak($('#maintext'), 1000, strings, 0);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maintext">init</div>
目标:jQuery插件
jQuery使得制作插件非常容易。一旦你开始在你的一个函数中使用像.text
或.fadeOut
这样的jQuery方法,你应该问自己jQuery插件是否更适合。
// non-plugin
speak($('#maintext', someStrings))
// plugin
$('#maintext').speak(someStrings)
我很确定你会同意我在这种情况下第二种选择要好得多。让我告诉你这样做有多容易。
($ => {
// this function doesn't have to change at all
const speak = ($elem, time, [x,...xs]) => {
if (x === undefined) return null;
$elem.fadeOut(time, () => {
$elem.text(x).fadeIn(time, () => {
speak($elem, time, xs)
})
})
}
// create the plugin; sensible default value for `time`
$.fn.speak = function(strings, time=1000) {
return $(this).each((idx, elem) =>
speak($(elem), time, strings));
};
}) (jQuery);
$('#maintext').speak(['the', 'end', 'of', 'the world']);
$('#othertext').speak(['la', 'fin', 'du', 'monde']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maintext">init</div>
<div id="othertext">init</div>
现在它可以与页面上的多个元素无缝协作,甚至可以同时在元素上运行
答案 1 :(得分:-1)
function speak(num, arr, length, time)
{
console.log("Speak: " + num);
if(num < length)
{
var string = arr[num];
$("#maintext").text(string).promise().done(function(){
$("#maintext").fadeOut(time, function ()
{
if(num != length-1)
$("#maintext").fadeIn(time, speak(num+1, arr, length, time));
});
});
}
}
尝试用此替换说话功能。我添加了.promise()。它的作用是只有在插入值之后,fadeOut和fadeIn才会执行,我相信这会对你有帮助:)(/ p>