我怀疑是关于d3如何工作的一个相当基本的问题。我已经开始使用这个完美运行的代码并触发nodeClick动作...
var nodeEnter = node.enter()
.append("g")
.attr("class", "node")
.on("click", nodeClick)
但后来我改为使用点击功能来确定是单击还是双击......
.on("click", function(d) {
if some logic () {
console.log("double click");
} else {
console.log("single click only");
nodeClick;
}
})
这在输出正确的控制台消息方面非常有效,但似乎我对nodeClick的调用在嵌入到函数中时无法正常工作(即不触发节点点击行为)。我尝试更改为nodeClick()和nodeClick(d),但这只会导致错误。
我错过了可以解释这种行为的东西吗?对我来说似乎很奇怪,我看到了从函数外部和内部调用“nodeClick”的两种不同行为。
感谢您的帮助!
这是完整的代码......
dblclick_timer = false;
//.on("click", nodeClick) //works perfectly
.on("click", function(d) {
if ( dblclick_timer ) {
clearTimeout(dblclick_timer)
dblclick_timer = false
console.log("double click");
d.fixed=false;
}
else dblclick_timer = setTimeout( function(){
dblclick_timer = false
console.log("single click only");
d3.select(this).nodeClick;
}, 250)
})
经过所有很好的反馈,这是通过在d3.event变为空之前存储它的工作解决方案......
.on("click", function(d,i) {
var cacheEvent = d3.event;
if ( dblclick_timer ) {
clearTimeout(dblclick_timer)
dblclick_timer = false
console.log("double click");
d.fixed=false;
force.start();
}
else dblclick_timer = setTimeout( function(){
dblclick_timer = false
console.log("single click only");
d3.event = cacheEvent;
nodeClick.call(d3.select(this), d, i);
}, 250)
})
答案 0 :(得分:2)
如第一条评论所述,你必须建立正确的上下文:它是一个javaScript的东西,而不是d3的东西。如果您建立了正确的this
上下文并传递相同的参数,它将完全相同。关键是使用Function.prototype.call
来调用回调。这是standard javaScript。
.on("click", function(d, i) {
if some logic () {
console.log("double click");
} else {
console.log("single click only");
nodeClick.call(this, d, i);
}
})
中所述
以与其他运算符相同的方式调用指定的侦听器 函数,传递当前数据d和索引i,用这个 context作为当前的DOM元素。
答案 1 :(得分:1)
正如评论中指出的那样,您实际上并没有调用该函数。在案件中
.on("click", nodeClick)
安装函数nodeClick()
作为click事件的处理程序。这里nodeClick
引用函数对象 - 即函数本身,而不是它可能为特定输入返回的任何值。
在第二种情况下,你做同样的事情,除了你传入匿名(即在现场定义)功能而不是命名功能。在这两种情况下,都会在事件发生时调用该函数。
语句nodeClick;
本身没有任何效果 - 它与1;
或foo;
基本相同,其中foo
是其他地方定义的变量或函数。
要使其工作,您需要调用该函数 - 在名称后添加()
。此外,您需要传递回调收到的任何参数 - nodeClick(d)
。您还需要使用相同的this
上下文来调用它,因为函数的实现依赖于它。如果您使用selection.each()
:
d3.select(this).each(nodeClick);