如何在不丢失格式的情况下连续淡入() 元素文本的每个字符,包括嵌套元素

How to continuously fadeIn() each character of an element text, including nested elements, without losing formatting?

本文关键字:元素 文本 嵌套 包括 字符 淡入 连续 情况下 格式      更新时间:2023-09-26

我的客户强迫我使用他在以前的网站上使用的一些脚本来缓慢而流畅地加载文章的文本。脚本有效,但问题是格式(<strong>)在某处丢失了,而不是三个不同的段落,我把所有段落放在一起三次......

.HTML

<article id="post-5" class="post-5 page type-page status-publish hentry" style="overflow: hidden; width: auto; height: 400px;">
  <div class="col-6 column">                      
    <p><strong>Je mi přes 40 a jsem žena.</strong></p>
    <p><strong>Snažila jsem se zařadit, zmoudřet a mít klid. Nepodařilo se.</strong></p>
    <p style="text-align: justify;">Teď se už předělávat nehodlám. A víte co? Strašně si to užívám. Prozkoumávám svou zběsilost v srdci, ženskou marnivost i potřebu mít věci pod kontrolou. Zjistila jsem, že svět je báječné místo k žití, že život není vždycky fér, ale c´est la vie, že být sexy neznamená být krásná, že být úspěšná, neznamená být chytrá, že když se člověk nebere smrtelně vážně, tak je to vlastně skvělá jízda a že můj “bucketlist” je zatraceně dlouhý. Také, že když se nám “povedou” děti, věříme na geny, ale když jsou děti svérázné a my čelíme neustále zvednutému obočí okolí a máme pocit selhání – je lepší nechat to být a doufat, že se dobré geny nakonec “proberou”, protože to jediné, na čem opravdu záleží, jsou hodnoty a důvěra v sebe i svět okolo nás, neopomíjet tu krásu a čistotu, která dětství provází, tu lásku, kterou jsme schopni získat i dávat a užít si čas, který nám byl dán. Svět je plný silných příběhů a skvělých lidí a já jsem se rozhodla, že v čase, který mi byl vyměřen, je chci potkávat, chci se jimi inspirovat a tuto inspiraci předávat dál.</p>                  
  </div>
</article>

爪哇语

var header = $('.post-5 div p');
var title = header.text();
header.text('');        
var arrayTitle = title.split('');
var i = 0;
var interval = setInterval(function(){
    if (i > arrayTitle.length) {
        setTimeout(function(title) {
            header.text(title);
        }, 1000, title);
        //header.text(title);
        clearInterval(interval);
    } else {
        $('<span>')
        .text(arrayTitle[i])
        .appendTo(header)
        .hide()
        .fadeIn(1000);
        i++;      
    }
}, 30);
在这里,你

使用Codepen,你可以看到它对文本做了什么。我真的很感激你的帮助。

(...) 问题是格式 ( <strong> ) 在某处丢失了 (...)

.text() 方法返回元素(及其后代)的纯文本,不带标记。
为了获取包含标签的文本,jQuery有一个.html()方法。但是,这也不适用于您的代码(除非使用正则表达式)。这是因为您将文本分解为单个字符:

var arrayTitle = title.split('');

然后将所有字符包装成<span>

$('<span>')
  .text(arrayTitle[i])
  //...

因此,即使使用未擦除标签的.html(),标签的每个字符也会包装到<span>元素中,因此结果如下(<strong>):

<span>&lt;</span>
<span>s</span>
<span>t</span>
<span>r</span>
<span>o</span>
<span>n</span>
<span>g</span>
<span>&gt;</span>
...

(...) 而不是三个不同的段落,我把所有段落放在一起三次

这是这些行的结果:

var header = $('.post-5 div p');
var title = header.text();

那里实际发生的事情是,header指向一个包含所有<p>元素的对象。
title是从该对象内的所有元素中提取的文本。
因此,header中的每个项目(每个<p>)都填充了所有三个<p>元素的文本。


溶液

您需要遍历<p>元素以分别处理每个元素:

$('.post-5 div p').each(function(){
    // $(this) points to the current <p> element instead of all:
    var header = $(this);
    // ...
});

如果代码应该只使用严格指定的 HTML 标记,这可能会让您更接近。
然后,您可以使用 if 语句来检查一些条件并运行原始代码:

// declare current timeout variable:
var delay = 0;
$('.post-5 div p').each(function(){
    // declare <strong> element as current 'header':
    var header = $(this).find('strong');
    // if it's not found:
    if(!header.length){
        // declare <p> instead as current 'header':
        header = $(this);
    }
    // ... your code ...
    // Then wrap your setInterval with a setTimeout to not fade each <p> at once:
    setTimeout(function(){
        var interval = setInterval(function(){
            // ... your code ...
        }, 30);
    // set timeout on which the current 'header' should start fading:    
    },delay);
    // update delay for the next <p> element:
    delay += 30*arrayTitle.length;
});

这是代码的快速修复,考虑到它与静态 HTML 标记一起使用。

附加方式(清洁剂)


另一种解决方案

为了使代码处理具有多个嵌套标签的内容,首先应将文本和元素分开以使标签完好无损。
它可以使用.contents()(jQuery)和nodeType(javascript)来完成。

.contents() 返回一个子元素数组,对于该 HTML 示例:

Hello <b>World</b> <span>Foo Bar</span>

结果将是:

nodeType:3  |  nodeType:1  |  nodeType:3  |  nodeType:1
 [Hello ]   |   [World]    |     [ ]      |  [Foo Bar]

然后,您可以遍历该数组并将字符包装到<span>中,前提是nodeType === 3,否则再次为该节点运行函数:

function spanifyText(el){
    $(el).contents().each(function(){
        // check if the element is not a text node:
        if(this.nodeType !== 3){
            // not a text node, run method again for that element:
            return spanifyText(this);
        }
        // it's a text node. Process it:
        $(this).replaceWith('<span class="fade">'+$(this).text().split('').join('</span><span class="fade">')+'</span>');
    });
}
spanifyText('.post-5 div p');
// after processing, hide each character and fade it:
$('.fade').hide().each(function(i){
    $(this).delay(i*30).fadeIn(function(){
        // unwrap the character after animation, so that it is no longer inside a <span>:
        $(this).contents().unwrap();
    });
});

演示


引用

  • .each()
  • .text()
  • .html()
  • .delay()
  • .unwrap()
  • .contents()
  • .replaceWith()
  • nodeType

.text() 抓取的是文本而不是 html。使用 .html()

$('.post-5 div p');

给出三个结果,而不仅仅是一个。

如果要使用相同的效果,则必须完全修改脚本。