【问题标题】:Letter-by-letter text appearance animation with CSS使用 CSS 的逐字母文本外观动画
【发布时间】:2013-11-15 00:47:40
【问题描述】:

我有一个带有文字的<div>

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。

我希望 <div> 中的文字一次出现在一个字符的页面上:

大号 罗 洛尔 ... 以此类推,直到全文可见

可接受的替代方案:一次只做一个单词,以避免 HTML 实体出现问题以及由于软连字符而导致单词跳跃。

如果用户点击<div>,它应该取消动画并立即显示全文。

简而言之,我想模仿一个在日式冒险游戏中经常出现的动画。 (我认为这有时被称为打字机或电传打字机效果。)这是一个很好的例子:

http://www.youtube.com/watch?feature=player_detailpage&v=SasgN0lim7M#t=418

显然,我可以使用 JavaScript 编写动画脚本——只需设置一个计时器并一个接一个地附加字母(或单词)。

但是有没有可能在现代浏览器中使用 CSS 来做我需要的事情? (当然,我至少需要用 JS 更改 onclick 中的元素类,但没关系。)

更新:澄清字符与字母以及 HTML 实体的问题:

我的文本中到处都是 HTML:

Lo&shy;rem <i>ip&shy;sum</i>.

将文本附加到 innerHTML 一个字符一个字符的幼稚方法是行不通的:

大号 罗 罗& ……呸!

【问题讨论】:

  • 我认为最好的方法是做你已经建议的 - 带有计时器和附加字母的 JS
  • 嗯,有一件事是,浏览器比我写的 JS 代码更清楚什么是字母,什么不是。
  • 只做每个字符而不是一个字母,我认为这是一种正常的体验
  • 不,CSS 无法实现逐字符动画。您只能为文本的边界矩形设置动画以使其增长,但这不会给出typewriter effect
  • 如果你想通过 css 完成,那你为什么要标记 javascript?

标签: javascript html css animation


【解决方案1】:

你可以用一点 jQuery 来实现这一点。

看看我的小提琴:http://jsfiddle.net/kA8G8/7/

HTML

<p class="typewriter">Nullam id dolor id nibh ultricies vehicula ut id elit. Maecenas faucibus mollis interdum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>

JS

var text = $('.typewriter').text();

var length = text.length;
var timeOut;
var character = 0;


(function typeWriter() { 
    timeOut = setTimeout(function() {
        character++;
        var type = text.substring(0, character);
        $('.typewriter').text(type);
        typeWriter();

        if (character == length) {
            clearTimeout(timeOut);
        }

    }, 150);
}());

【讨论】:

  • 不适用于带有 HTML 实体的文本。我已更新问题以进一步澄清这一点。
【解决方案2】:

很遗憾,您无法使用 CSS 做到这一点,因此您将不得不恢复为纯 JS 方法。

正如您的 cmets 所解释的,您需要您的文本包含一些 HTML 标记,因此我建议逐字动画是处理该问题的最简单方法。像这样的:

var timer, fullText, currentOffset, onComplete, wordSet;

function Speak(person, text, callback) {
    $("#name").html(person);
    fullText = text;
    wordSet = text.split(" ");
    currentOffset = 0;
    onComplete = callback;
    timer = setInterval(onTick, 300);
}

function onTick() {
    currentOffset++;
    if (currentOffset == wordSet.length) {
        complete();
        return;
    }
    var text = "";
    for(var i = 0; i < currentOffset; i++){
     text += wordSet[i] + " ";   
    }
    text.trim();
    $("#message").html(text);
}

function complete() {
    clearInterval(timer);
    timer = null;
    $("#message").html(fullText);
    if (onComplete) onComplete();
}

$(".box").click(function () {
    complete();
});

Speak("Simon",
    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",

function () {
    setTimeout(function () {
        Speak("Javascript", "Simon has finished speaking!");
    }, 2000);
});

Here is a working example

注意:此代码可能会被大量重构以更高效和简洁,但它应该完整地展示这个概念。


我也是created a letter-by-letter example。虽然它不支持您的 html 标记需求,但它看起来确实更好,所以也许您可以调整它以适合您。

【讨论】:

    【解决方案3】:

    有一个纯 CSS 技巧可以做到这一点。

    使用掩码元素,甚至是伪元素p:beforep:after,其 z-index 比文本元素高。给它与文本背景和行高相同的颜色。将其放在文本上方的绝对位置。

    然后,您只需对其进行动画处理,使其向右移动,逐个字母地去除掩码。 这只是一种解决方法,因为如果您在文本下方有一个复杂的背景,例如图像,那么这个技巧很难重现,因为您必须将背景图像映射到遮罩元素上。

    【讨论】:

    • 有用的技巧,但只有当你能保证文本在一行时才有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多