D3: переход текста в стиле пишущей машинки

В этом jsfiddle, метка переходит от одного текста к другому, уменьшая шрифт старого текста и, в свою очередь, увеличивая шрифт нового текста.

Тем не менее, я хотел бы, чтобы новый текст apperar "печатная машинка", как в этом jsfiddle, Как написать собственный текстовый интерполятор D3, который позволит переходить текст таким способом "пишущей машинки"?

3 ответа

Решение

Интересные идеи, оба выполняют свою работу, но для этого есть специальный способ для d3: пользовательская функция анимации.

Скрипка здесь: 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() называется фабрикой анимации, потому что она создает функцию анимации для каждого элемента. Он выполняется один раз для каждого элемента (и обычно использует данные и индекс элемента в качестве параметров) в начале перехода. Он запускает любые расчеты установки и затем возвращает функцию анимации, которая будет использоваться во время перехода.

Возвращенная функция анимации также называется интерполятором, поскольку она вычисляет промежуточные значения. В этом случае это:

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

Эта функция будет вызываться при каждом "тике" перехода, и ей будет передано значение от 0 до 1, представляющее, как далеко через переход предполагается получить результат. (Скорость, с которой 0 изменяется на 1, будет варьироваться в зависимости от параметра замедления, я использовал линейное ослабление для постоянной скорости типа.)

Когда вы задаете пользовательские функции анимации для атрибутов или стилей, функция анимации возвращает значение, которое будет использоваться для этого атрибута или стиля в этой точке перехода. Для общего transition.tween()возвращаемые значения не используются, ваша функция должна сама вносить изменения - что я делаю, непосредственно устанавливая textContent свойство элемента. Я установил его на подстроку целевого текста, где количество символов в подстроке определяется t Параметр (который всегда находится в диапазоне от 0 до 1) и длина текста, так что весь текст набирается по длине перехода.

PS Вы также можете повеселиться с функцией ослабления. Легкость "отказов" делает вид, что машинистка не уверена в том, что они пишут:

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

Я дал этому шанс. Должен сказать, что у меня нет опыта 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 аргумента к этому row а также column чтобы я мог дать соответствующие задержки.

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/

Другие вопросы по тегам