我试图制作一个"控制台打字效果"使用js,并在下一个函数中我获取元素的文本,然后我使用" for"用于切片文本并在内部粘贴延迟的循环。
调试chrome中的代码后,我可以看到javascript没有运行setTimeout ......它只是忽略它。
function type() {
var text = document.querySelector('.console-effect').textContent;
for (var i = 0; i <= text.length; i++) {
setTimeout(function() {
document.querySelector('.console-effect').textContent = text.substr(0, i)
}, 50);
}
}
type();
答案 0 :(得分:3)
您的setTimeout
都在同一时间执行,因为for
循环不等待它们在每次迭代时执行。您必须使用50*i
等值来延迟每个超时。
然后,为了在这种情况下保留i
的值,您需要使用闭包。否则,当你的超时结束时,循环将结束,i
将是所有这些循环的最终值。
var text = document.querySelector('.console-effect').textContent;
for (var i = 0; i <= text.length; i++) {
(function(i) {
setTimeout(function() {
document.querySelector('.console-effect').textContent = text.substr(0, i);
}, 50*i);
})(i);
}
&#13;
body{background: #333;}
.console-effect{color: #0f0; font-family: monospace; font-size: 2em;}
&#13;
<div class="console-effect">This is some example text</div>
&#13;
答案 1 :(得分:1)
在Javascript中使用循环中的函数不是一个好主意,我有很糟糕的经验。
这样做的代码应该可以正常工作:
function type() {
var text = document.querySelector('.console-effect').textContent;
var loopFunc = function(i) {
return function() {
document.querySelector('.console-effect').textContent = text.substr(0, i)
};
};
for (var i = 0; i <= text.length; i++) {
setTimeout(loopFunc(i), 50);
}
}
type();
答案 2 :(得分:1)
我不想相信@blex,但他对范围是正确的。他做出的两点都是正确的,但封闭让我震惊。我怎么从来没有遇到过这种情况而被迫在以前解决问题呢?
所以这里的想法是,不是在开始时安排十几个调用你的函数,而是只安排下一个调用。在调用之后,它会看到是否需要安排下一个。
function type() {
var text = document.querySelector('.console-effect').textContent;
var i = 0;
var typeNext = function() {
++i;
document.querySelector('.console-effect').textContent = text.substr(0, i);
if(i < text.length) {
setTimeout(typeNext, 50);
}
}
setTimeout(typeNext, 50);
}
type();
&#13;
<span class="console-effect">This is a test</span>
&#13;
答案 3 :(得分:0)
var text = document.querySelector('.console-effect').textContent;
var index = 0;
setInterval(function(){
document.querySelector('.console-effect').textContent = text.substr(0, index);
if(index == text.lenght){
clearInterval(this);
}
index++;
},1000);
答案 4 :(得分:0)
做这样的事情。
function type() {
var text = document.querySelector('.console-effect').textContent;
document.querySelector('.console-effect').textContent = '';//clear content
for (var i = 0; i <= text.length; i++) {
setTimeout(function(j) {
document.querySelector('.console-effect').textContent += text[j];// or .charAt(j)
}, 50 * i, i);
// 50 * i sets timeout for each iteration
// i (3rd arg) passes to the inner function
}
}
type();
更好的版本。
function type(text) {
var textObj = document.querySelector('.console-effect');
for (var i = 0; i <= text.length; i++) {
setTimeout(function(ch) {
textObj.textContent += ch;
}, 50 * i, text[i]);
// 50 * i sets timeout for each iteration
// i (3rd arg) passes to the inner function
}
}
type('.console-effect');
答案 5 :(得分:0)
没有50 * i的解决方案,也看看css效果。问题是setTimeout是异步执行的(&#39;控制流&#39;不等待那些50ms),所以它们一起被激活,值i = text.length(如果你的文字足够小)
<p class="console-effect">console effects</p>
<script>
function type() {
var i=0;
var t = document.querySelector('.console-effect').textContent;
var fn = setInterval(function() {
print_text(++i,t,fn)
}, 500);
}
function print_text(i,t,fn){
if(i <= t.length){
document.querySelector('.console-effect').textContent = t.substr(0, i)
} else clearInterval(fn)
}
type();
</script>
<style>
@-webkit-keyframes blinker {
from { opacity: 1.0; }
to { opacity: 0.0; }
}
.console-effect:after{
content:'_';
text-decoration: blink;
-webkit-animation-name: blinker;
-webkit-animation-duration: 0.2s;
-webkit-animation-iteration-count:infinite;
-webkit-animation-timing-function:ease-in-out;
-webkit-animation-direction: alternate;
}
</style>
答案 6 :(得分:-2)
setTimeout只运行一次(在你的情况下延迟50ms后)。
为此,您应该使用setInterval