Как применить анимацию движения к буквам вместо цифр? - PullRequest
2 голосов
/ 09 июля 2019

Для перехода, который я применяю к текстовому объекту в d3.js, я хотел бы изменить текст, как в в этом примере .Однако моя проблема в том, что это не сработает, если текст состоит из букв, а не цифр, и до сих пор я нашел только примеры, в которых использовались только цифры.

Поэтому мой вопрос: возможно ли создать такойпереход анимации движения к текстовому объекту с буквами?

Вот как я в настоящее время применяю его (используя функцию interpolateString () ):

var mytext = svg.append("text")
    .style("fill", 'black')
    .attr("x", 0)
    .attr("y", 0)
    .style("font-size", "14")
    .text("My old text")

mytext
    .transition()
          .delay(1500)
          .duration(1000)
          .tween("text", function(d) { 
              var self = d3.select(this)
                var i = d3.interpolateString(self.text().replace(/,/g, ""), "My new text");
                    return function(t) {self.text(i(t))};
              });


1 Ответ

3 голосов
/ 09 июля 2019

У вас неправильное представление о том, что делает interpolateString. Если вы посмотрите на API , вы увидите, что это ...

Возвращает интерполятор между двумя строками a и b. Строковый интерполятор находит числа , встроенные в a и b, где каждое число имеет форму, понятную JavaScript (выделено мной)

Таким образом, он не будет интерполировать строки, сделанные только буквами.

Это, как говорится, привело нас к вопросу: как вы хотите интерполировать буквы? Например, вы можете интерполировать их в соответствии с их положением в латинском алфавите. Если это так, это способ сделать это:

Создать массив с алфавитом ...

const alphabet = " abcdefghijklmnopqrstuvwxyz".split("");

... и, в функции tween, интерполируют индекс каждой буквы в алфавите от старого текста к новому тексту:

.tween("text", function() {
    return function(t) {
      d3.select(this).text(oldText.map(function(d,i){
        return alphabet[~~(d3.interpolate(alphabet.indexOf(d), alphabet.indexOf(newText[i]))(t))]
      }).join(""))
    };
});

Это очень простой подход, который будет работать, только если две строки имеют одинаковую длину. Также обратите внимание на то, что я помещаю пробел в массив alphabet, в противном случае мы получим undefined для пробелов в строках.

Вот демоверсия:

const svg = d3.select("svg")
const oldText = "this is my old text".split("");
const newText = "here is my new text".split("");
const alphabet = " abcdefghijklmnopqrstuvwxyz".split("");
const text = svg.append("text")
  .attr("y", 50)
  .attr("x", 20)
  .attr("font-size", 30)
  .text(oldText.join(""));
text.transition()
  .delay(500)
  .duration(2000)
  .ease(d3.easeLinear)
  .tween("text", function() {
    return function(t) {
      d3.select(this).text(oldText.map(function(d, i) {
        return alphabet[~~(d3.interpolate(alphabet.indexOf(d), alphabet.indexOf(newText[i]))(t))]
      }).join(""))
    };
  });
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
...