如何在字母而不是数字上应用补间功能?

时间:2019-07-09 04:07:47

标签: d3.js svg string-interpolation tween

对于在d3.js中应用于文本对象的过渡,我希望像在 this example 中那样对文本进行补间。但是,我的问题是,如果文本是由字母而不是数字组成的,那么这将无法正常工作,直到现在,我仅发现仅使用数字的示例。

所以我的问题是:是否可以在带有字母的文本对象上创建这样的补间过渡?

这是我当前使用它的方式(使用interpolateString() function):

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 个答案:

答案 0 :(得分:3)

您对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>