0

过去一天我一直在努力解决这个问题。

我正在尝试制作一些时髦的文本效果,基本上是一种美化的字符串创建。它写一行有点像广告牌,为此我使用了 setTimeout。事情是我想把它放在一个函数中,这样我就可以重用它并在不同的元素上多次调用它。

问题是我需要将文本更新为新文本的一半。为此,我清除了超时,但除非计时器变量超出范围,否则它不会清除。

由于实用性,我真的不能在功能之外拥有它;我不确定它会被调用多少次,在函数外部声明 20 个时间变量感觉不对。

这是在一项上正确运行的代码多次单击以中断并重新启动)

    var t;
    function writeStats(str,dest) {

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        function randomChar(type){
            var pool = "";

            if (type == "lowerLetter"){
                pool = "abcdefghijklmnopqrstuvwxyz0123456789";
            }
            else if (type == "upperLetter"){
                pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            }
            else if (type == "symbol"){
                pool = ",.?/\\(^)![]{}*&^%$#'\"";
            }

            var arr = pool.split('');
            return arr[Math.floor(Math.random()*arr.length)];
        }

        str = str.split('');

        var types = [],
            letters = [];

        for(var i=0;i<str.length;i++){

            var ch = str[i];

            if(ch == " "){
                types[i] = "space";
                continue;
            }
            else if(/[a-z]/.test(ch)){
                types[i] = "lowerLetter";
            }
            else if(/[A-Z]/.test(ch)){
                types[i] = "upperLetter";
            }
            else {
                types[i] = "symbol";
            }

            letters.push(i);
        }

        clearTimeout(t);

        (function shuffle(start){

            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i,
                len = letters.length,
                strCopy = str.slice(0); // Fresh copy of the string

            if(start>len){
                return;
            }

            // All the work gets done here
            for(i=Math.max(start,0); i < len; i++){

                // The start argument and options.step limit
                // the characters we will be working on at once

                if( i < start+options.step){
                    // Generate a random character at this position
                    strCopy[letters[i]] = randomChar(types[letters[i]]);
                }
                else {
                    strCopy[letters[i]] = "";
                }
            }

            //el.text(strCopy.join(""));
            el = strCopy.join("");
            //console.log(el);
            $('.'+dest).text(el);

            t = setTimeout(function(){

                shuffle(start+1);

            },500/options.fps);

        })(-options.step);

    }

    $(document).ready(function(){
        $(document).click(function(){
            writeStats('this sentence is a great one','t1');
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="t1"></div>
<div class="t2"></div>
和一个小提琴脚本:https ://jsfiddle.net/phjzfw15/

如果我将 t 变量带入函数内部,它就不会像以前那样工作:

function writeStats(str,dest) {
        var t;
        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        function randomChar(type){
            var pool = "";

            if (type == "lowerLetter"){
                pool = "abcdefghijklmnopqrstuvwxyz0123456789";
            }
            else if (type == "upperLetter"){
                pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            }
            else if (type == "symbol"){
                pool = ",.?/\\(^)![]{}*&^%$#'\"";
            }

            var arr = pool.split('');
            return arr[Math.floor(Math.random()*arr.length)];
        }

        str = str.split('');

        var types = [],
            letters = [];

        for(var i=0;i<str.length;i++){

            var ch = str[i];

            if(ch == " "){
                types[i] = "space";
                continue;
            }
            else if(/[a-z]/.test(ch)){
                types[i] = "lowerLetter";
            }
            else if(/[A-Z]/.test(ch)){
                types[i] = "upperLetter";
            }
            else {
                types[i] = "symbol";
            }

            letters.push(i);
        }

        clearTimeout(t);

        (function shuffle(start){

            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i,
                len = letters.length,
                strCopy = str.slice(0); // Fresh copy of the string

            if(start>len){
                return;
            }

            // All the work gets done here
            for(i=Math.max(start,0); i < len; i++){

                // The start argument and options.step limit
                // the characters we will be working on at once

                if( i < start+options.step){
                    // Generate a random character at this position
                    strCopy[letters[i]] = randomChar(types[letters[i]]);
                }
                else {
                    strCopy[letters[i]] = "";
                }
            }

            //el.text(strCopy.join(""));
            el = strCopy.join("");
            //console.log(el);
            $('.'+dest).text(el);

            t = setTimeout(function(){

                shuffle(start+1);

            },500/options.fps);

        })(-options.step);

    }

    $(document).ready(function(){
        $(document).click(function(){
            writeStats('this sentence is a great one','t1');
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="t1"></div>
    <div class="t2"></div>
...如果你喜欢的话,还有相对的小提琴:https ://jsfiddle.net/phjzfw15/1/

如果您运行该代码段,您会发现它不再正常工作。反复单击将显示旧句子仍然存在并且被覆盖。如何在函数内正确清除超时?

我认为“t”变量是每个函数的本地变量,并且会创建一个单独的实例?

谢谢!

4

2 回答 2

0

好的,这是一个简化的版本(可能之前的代码量太多了) 正确的版本

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];

    var timer;

    function writeStats(str, dest) {
        
        $('.'+dest).text('');

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        str = str.split('');
        
        clearTimeout(timer);
        var ll = '';
        (function shuffle(start){
            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i, len = str.length, el;
            

            if(start>=len){
                return;
            }          
            ll = ll + str[start];
            $('.'+dest).text(ll);

            timer = setTimeout(function(){

                shuffle(start+1);

            },1500/options.fps);
        })(0);

    }

    $(document).ready(function(){
        var index = 0;
        $(document).click(function(){
            writeStats(starr[index],'t1');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
Correct version
<div class="t1">Click anywhere multiple times</div>

不工作版本

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];



    function writeStats(str, dest) {
        var timer;
        $('.'+dest).text('');

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        str = str.split('');
        
        clearTimeout(timer);
        var ll = '';
        (function shuffle(start){
            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i, len = str.length, el;
            

            if(start>=len){
                return;
            }          
            ll = ll + str[start];
            $('.'+dest).text(ll);

            timer = setTimeout(function(){

                shuffle(start+1);

            },1500/options.fps);
        })(0);

    }

    $(document).ready(function(){
        var index = 0;
        $(document).click(function(){
            writeStats(starr[index],'t1');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
NOT WORKING VERSION (please note I just moved the timer declaration inside the function)
<div class="t1">Click anywhere multiple times fast</div>

于 2015-04-29T15:14:31.650 回答
0

终于让它工作了。为后人...

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];

        var writer = function(){
            
            var timer;

            this.writeStat = function(str,dest) {

                var options = { "step"  : 8, "fps"   : 25, "text"  : "" }
                
                str = str.split('');
                
                clearTimeout(timer);
                var ll = '';
                
                (function shuffle(start){
                    // This code is run options.fps times per second
                    // and updates the contents of the page element
        
                    var i, len = str.length, el;
                    
        
                    if(start>=len){
                        return;
                    }          
                    ll = ll + str[start];
                    $('.'+dest).text(ll);
        
                    timer = setTimeout(function(){
        
                        shuffle(start+1);
        
                    },1500/options.fps);
                })(0);
            }
        }

    $(document).ready(function(){
        var index = 0;
        w = new writer;
        y = new writer;
        $(document).click(function(){
            
            w.writeStat(starr[index],'t1');
            y.writeStat(starr[index],'t2');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="t1"></div>
<div class="t2"></div>

于 2015-04-30T09:02:07.023 回答