javascript - 按字符写入/删除文本

标签 javascript jquery substring

我尝试按字符更改任何文本(按字符显示文本,按字符删除文本并按字符显示另一个字符)。

我实际上拥有什么?

var i = 0;
var terms = ['text  <b>bold</b>', 'longer text <b>bold</b>', '<b>bold</b> text 3'];

var timer = setInterval(function() {
    var el = $('#el');
    var wr = $('#wr');

    setInterval(function() {
        var str = el.html(); // doesn't work (still shows all content, not sliced one)
        el.html(str.substring(0, str.length - 1));
    }, 300 / str.length); // (300 / str.length) - do all animation in 300s

    i++;

    if (i === 3) {
        i = 0;
    }

}, 2500);

我在切片最后一个字符时遇到问题,所以到目前为止我还没有添加新文本:-(

我尝试过的变体之一:

...
var text = terms[i].split('');

setInterval(function() {
        el.html(text); // add sliced text in loop... not working as expected            
        // ...    
        text = text.slice(0, -1); // slice text by last character
    }, 300 / text.length); 

好的,根据评论,稍微解释一下

我有一个元素

<span id=el>text <b>bold</b></span>

在 300 毫秒的时间间隔内,我需要逐个字符地删除此文本。

<span id=el>text <b>bold</b></span>
<span id=el>text <b>bol</b></span>
<span id=el>text <b>bo</b></span>
<span id=el>text <b>b</b></span>
<span id=el>text <b></b></span> // remove 'b'
<span id=el>text</span> // remove ' ' and empty bold
<span id=el>tex</span>
<span id=el>te</span>
<span id=el>t</span>
<span id=el></span>
// now element is empty, since start it's 300ms

// and now I need to put there new text, char by char (whole phrase 300ms again)
<span id=el>l</span>
<span id=el>lo</span>
<span id=el>lon</span>
...
<span id=el>longer tex</span>
<span id=el>longer text</span>
<span id=el>longer text </span> // add space
<span id=el>longer text <b>b</b></span> // add 'b' into bold
<span id=el>longer text <b>bo</b></span>
<span id=el>longer text <b>bol</b></span>
<span id=el>longer text <b>bold</b></span>
// after 2500ms remove this char by char again and replace by third. Etc.

等等。你能帮我吗?过去两天尝试过,多次尝试,没有结果......
谢谢

最佳答案

这就是我组织代码来缩小和增大元素的方式。我能做到这一点的唯一明智的方法是首先替换 <>通过相应的实体代码&lt;&gt;这样这些字符就不会被解释为实际的标签。这些 4 个字母的实体代码将被删除并作为一个单元添加。通过这种方式,您可以将字符串从右向左一次收缩一个准字符,并且始终保持有效的 HTML。

Promise api(实际上是 jQuery 的 $.Deferred 版本)用于能够以确定性的方式知道收缩-增长周期(这是一个异步过程)何时完成,然后开始 2500 毫秒的延迟(这是另一个异步过程),然后重新开始。

$(function() {

    function shrink_grow(resolve, term)
    {
        term = term.replace(/</g, '&lt;').replace(/>/g, '&gt;');

        let el = $('#el');
        el.html(term);

        let interval = setInterval(shrinker, 30);

        function shrinker()
        {
            let str = el.html();
            let n = str.length >= 4 && (str.endsWith('&gt;') || str.endsWith(`&lt;`)) ? 4 : 1;
            el.html(str.substr(0, str.length - n));
            if (str.length === 0) {
                clearInterval(interval);
                interval = setInterval(grower, 30);
            }
        }


        function grower()
        {
            let str = el.html();
            if (str.length == term.length) {
                clearInterval(interval);
                resolve(undefined); // we are done
            }
            else if (str.length <= term.length - 4 && (term.substr(str.length + 1, 4) == '&lt;' || term.substr(str.length + 1, 4) == '&gt;')) {
                el.html(term.substr(0, str.length + 4));
            }
            else {
                el.html(term.substr(0, str.length + 1));
            }
        }

    }

    function pause(milliseconds)
    {
        // Create a new Deferred object
        var deferred = $.Deferred();

        // Resolve the Deferred after the amount of time specified by milliseconds
        setTimeout(deferred.resolve, milliseconds);

        return deferred.promise();
    }


    let terms = ['text <b>bold</b>', 'longer text <i>italic</i> text', '<b>bold</b> text 3'];
    let term_number = 0;
    let deferred = $.Deferred();
    let promise = deferred.promise();
    shrink_grow(deferred.resolve, terms[term_number++]);
    promise.then(function() {
        pause(2500).then(function() {
            let deferred = $.Deferred();
            let promise = deferred.promise();
            shrink_grow(deferred.resolve, terms[term_number++]);
            promise.then(function() {
                pause(2500).then(function() {
                    let deferred = $.Deferred();
                    let promise = deferred.promise();
                    shrink_grow(deferred.resolve, terms[term_number++]);
                    promise.then(function() {
                        console.log('done');
                    });
                });
            });
        });
    });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="el"></span>

并保持标签完整

然而,这非常复杂:

$(function() {

    let TOTAL_TIME = 300;

    function shrink_grow(resolve, term)
    {
        let el = $('#el');

        let matches = term.match(/<([^>])+>(.*?)<\/\1>/); // look for internal tag
        let internalTagTextLength = matches ? matches[2].length : 0;
        let internalTagText = internalTagTextLength ? matches[2] : '';
        let strlen = term.length;
        if (matches) {
            strlen -= matches[1].length * 2 + 5;
        }
        let shrinkGrowInterval = TOTAL_TIME / strlen;
        if (shrinkGrowInterval < 16) {
            shrinkGrowInterval = 16;
        }

        let interval = setInterval(grower, shrinkGrowInterval);

        function shrinker()
        {
            let str = el.html();
            let matches = str.match(/<([^>])+>(.*?)<\/\1>$/); // <i>text</i> at end of string, for example
            if (matches) {
                let str2 = matches[2];
                if (str2.length < 2) { // get rid of entire tag
                    str2 = matches[0];
                    let n = str2.length;
                    let l = str.length - n;
                    el.html(str.substr(0, l));
                    if (l === 0) {
                        clearInterval(interval);
                        resolve(undefined); // we are done
                    }
                }
                else {
                    let str2a = str2.substr(0, str2.length - 1);
                    str = str.replace(/<([^>])+>(.*?)<\/\1>$/, '<' + matches[1] + '>' + str2a + '</' + matches[1] + '>');
                    el.html(str);
                }
            }
            else {
                el.html(str.substr(0, str.length - 1));
                if (str.length === 0) {
                    clearInterval(interval);
                    resolve(undefined); // we are done
                }
            }
        }


        function grower()
        {
            let str = el.html();
            if (str.length == term.length) {
                clearInterval(interval);
                interval = setInterval(shrinker, shrinkGrowInterval);
            }
            else {
                let matches = term.substr(str.length).match(/^<([^>])+>(.*?)<\/\1>/);  // start of <i>text</i>, for example?
                if (matches) {
                    let str2 = '<' + matches[1] + '>' + matches[2].substr(0, 1) + '</' + matches[1] + '>';
                    el.html(str + str2);
                }
                else {
                    let matches = str.match(/<([^>])+>(.*?)<\/\1>$/); // <i>text</i> at end of string, for example
                    if (matches) {
                        let str2 = matches[2];
                        let l = str2.length;
                        if (l == internalTagTextLength) {
                            el.html(term.substr(0, str.length + 1));
                        }
                        else {
                            let str2a = internalTagText.substr(0, l + 1);
                            str = str.replace(/<([^>])+>(.*?)<\/\1>$/, '<' + matches[1] + '>' + str2a + '</' + matches[1] + '>');
                            el.html(str);
                        }
                    }
                    else {
                        el.html(term.substr(0, str.length + 1));
                    }
                }
            }
        }

    }


    let terms = ['text <b>bold</b>', 'longer text <i>italic</i> text', '<b>bold</b> text 3'];
    let nTerms = terms.length;
    let termNumber = -1;

    function callShrinkGrow()
    {
        if (++termNumber >= nTerms) {
            termNumber = 0;
        }
        let deferred = $.Deferred();
        let promise = deferred.promise();
        shrink_grow(deferred.resolve, terms[termNumber]);
        promise.then(callShrinkGrow);
    }

    callShrinkGrow();

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<span id="el"></span>

关于javascript - 按字符写入/删除文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59519165/

相关文章:

Javascript 结果到 div

java - java中如何严格查找字符串的子串?

c - 函数替换子字符串返回错误答案

javascript - 如何使用 javascript 动态设置 dewplayer 的数据

javascript - 在javascript中使用像美元符号这样的下划线

javascript - 确定弱/好/强密码的算法

javascript - HTML 通过点击编辑按钮使 Div 可编辑

javascript - 如何使背景图像位置在所有分辨率下保持相同?

jquery - 检查是否选中了单选框

Java与正则表达式、子串