我正在尝试在点击时更新我的文本元素,就像输入一样。当我单击文本时,它应该从数据数组中拉出下一个文本元素并逐个字符地打印直到完成,但是没有任何反应。尽管没有错误。下面附有代码。
var data = [
"Hello",
"World!",
"What's up?"
];
var i = 0;
var body = d3.select("body");
var element = body.append("svg");
element.append("text")
.data(data)
.text(function(d) {return d})
.attr("x", 150)
.attr("y", 75)
.attr("text-anchor", "middle")
.attr("fill", "white")
.on("click", function() {
d3.select(this).transition()
.duration(5000)
.ease(d3.easeLinear)
.tween("text", function () {
var newText = data[i];
var textLength = newText.length;
return function (t) {
this.textContent = newText.slice(0, Math.round(t * textLength));
};
});
//wrap around function for the data
i = (i + 1) % data.length;
});
答案 0 :(得分:4)
D3 version 5.8.0引入了一项重大变化:
补间功能现在可以使用
this
来引用当前节点。
因此,使用D3 v5.8.0或更高版本,您的代码就可以>>。
问题只是最内层函数中this
的含义。
与大多数D3方法一样,this
是当前的DOM元素。对于transition.tween,它并没有什么不同:
当转换开始时,将为每个所选元素评估值函数,按顺序传递当前数据d和索引i,并将
this
上下文作为当前DOM元素。 (强调我的)
但是,在内部函数中,this
只是window。
最简单的解决方案是在外部函数中使用var self = this
:
.tween("text", function() {
var self = this;
var newText = data[i];
var textLength = newText.length;
return function(t) {
self.textContent = newText.slice(0, Math.round(t * textLength));
};
});
这是您更新的代码:
var data = [
"Hello",
"World!",
"What's up?"
];
var i = 0;
var body = d3.select("body");
var element = body.append("svg");
element.append("text")
.data(data)
.text(function(d) {
return d
})
.attr("x", 150)
.attr("y", 75)
.attr("text-anchor", "middle")
.on("click", function() {
d3.select(this).transition()
.duration(5000)
.ease(d3.easeLinear)
.tween("text", function() {
var self = this;
var newText = data[i];
var textLength = newText.length;
return function(t) {
self.textContent = newText.slice(0, Math.round(t * textLength));
};
});
//wrap around function for the data
i = (i + 1) % data.length;
});

<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;