如何在字母而不是数字上应用补间函数?
How to apply a tween function on letters instead of numbers?
对于我在 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))};
});
您对 interpolateString
的作用有误解。如果您查看 API,您会发现它...
Returns an interpolator between the two strings a and b. The string interpolator finds numbers embedded in a and b, where each number is of the form understood by JavaScript (emphasis mine)
因此,它不会插入仅由字母组成的字符串。
话虽这么说,但它引出了一个问题:你想如何插入字母?例如,您可以根据它们在罗马字母表中的位置对它们进行插值。如果是这样,这是一种方法:
用字母创建一个数组...
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
数组中放置了一个 space,否则我们将在字符串中的 space 中得到 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>
对于我在 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))};
});
您对 interpolateString
的作用有误解。如果您查看 API,您会发现它...
Returns an interpolator between the two strings a and b. The string interpolator finds numbers embedded in a and b, where each number is of the form understood by JavaScript (emphasis mine)
因此,它不会插入仅由字母组成的字符串。
话虽这么说,但它引出了一个问题:你想如何插入字母?例如,您可以根据它们在罗马字母表中的位置对它们进行插值。如果是这样,这是一种方法:
用字母创建一个数组...
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
数组中放置了一个 space,否则我们将在字符串中的 space 中得到 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>