D3:打字机风格的文本转换

时间:2014-02-05 02:06:25

标签: javascript d3.js label transition interpolation

在此jsfiddle中,标签通过减少旧文本的字体从一个文本转换到另一个文本,从而增加新文本的字体。

但是,我希望以“打字机”的方式将新文本用于上传,就像在jsfiddle中一样。如何编写自定义D3文本插补器,以这种“打字机”方式启用文本转换?

3 个答案:

答案 0 :(得分:8)

有趣的想法,都可以完成工作,但有一种特定于d3的方法:自定义tween function

在这里小提琴:http://jsfiddle.net/QbysN/3/

代码:

function transition() {
    d3.select('text').transition()
        .duration(5000)
        .ease("linear")
        .tween("text", function () {
            var newText = data[i];
            var textLength = newText.length;
            return function (t) {
                this.textContent = newText.substr(0, 
                                   Math.round( t * textLength) );
            };
        });

    i = (i + 1) % data.length;
}

传递给.tween()的外部函数称为 tween factory ,因为它为每个元素创建了补间函数。在转换开始时,每个元素执行一次(通常使用元素的数据和索引作为参数)。它运行任何设置计算,然后返回将在转换期间使用的补间函数。

返回的补间函数也称为插值器,因为它计算中间值。在这种情况下,它是:

function (t) {
   this.textContent = newText.substr(0, Math.round( t * textLength) );
};

此函数将在转换的每个“tick”处被调用,并传递0到1之间的值,表示结果应该在转换的距离。 (0更改为1的速率将根据缓动参数而变化,我使用线性缓动来获得稳定的类型。)

当您为属性或样式指定自定义补间函数时,补间函数将返回在转换中该点处用于该属性或样式的值。对于泛型transition.tween(),不使用返回值,您的函数必须实际进行更改 - 我通过直接设置元素的textContent属性来执行此操作。我将它设置为目标文本的子字符串,其中子字符串中的字符数由t参数(始终在0和1之间)和文本的长度确定,以便整个文本在转换的长度内输入。

P.S。您也可以享受缓动功能。 “弹跳”的轻松使得打字员看起来不确定他们写的是什么:

http://jsfiddle.net/QbysN/4/

答案 1 :(得分:2)

我试了一下。我必须说我之前没有任何D3经验。我试图得到你展示的两个小提琴的组合。我认为仍然需要做一些清理以及何时停止打字,但这些应该是微不足道的。

查看jsFiddle

<强> HTML:

<div id="writer">
    <span id='sentence'></span>
    <span id='char'></span>
</div>

<强> CSS:

#writer{ 
    border: 1px solid black; 
    width:300px; 
    min-height: 200px;
    margin: auto;
}
span
{
    float:left;
}

<强> JavaScript的:

var text = "Hello World! I'm some typed text!";
var counter = 0;
var speed = 50;

function type()
{
    var sentence = document.getElementById("sentence");
    var lastText = sentence.innerHTML;
    var nextChar = text.charAt(counter);

    counter++;

    transition(nextChar,    
    function()
    {        
        lastText+=nextChar;
        sentence.innerHTML = lastText;
        setTimeout(type, speed);
    });  
}

function transition(char, onComplete) {
    d3.select('#char').transition()  
        .text("")
        .duration(300)
        .style("font-size","1px")
        .transition()
        .duration(300)
        .text(char)
        .style("font-size","16px")
        .each("end", onComplete);
}


type();

答案 2 :(得分:2)

我认为文本会更容易自动输入。因此,我遍历每个字符并调用过渡方法。我向它添加了2个参数rowcolumn,以便我可以给出适当的延迟。

data.forEach(function(d,row) {
    d.split("").forEach(function(d,column) {
        transition(row,column);
    });
});

function transition(row,column) {
   d3.select('text').datum(data[row].split("").slice(0,column+1))
    .transition()
    .delay(function(d) { return (row*5000) + (column*50); } )
    .text(function(d){return d.join("");});
}

试试这个小提琴:http://jsfiddle.net/QbysN/2/