我正在尝试在d3中实现一个on click事件,但我也希望有一个选项来转换单击相同的svg元素以触发不同的功能。如果我点击元素,我希望它叫我clicked()函数,但如果我移动点击元素,我希望它将它的填充样式更改为“steelblue”。我想做的是:
.on("click", function(d){
if (d3.event.shiftKey) {
d3.select(this).style("fill", "steelblue");
}
clicked(d);
})
但是我刚从d3得到“未捕获的TypeError:t.getAttribute不是函数”,因为我没有正确调用或传递了clicked()函数。
如果我这样做:
.on("click", clicked);
我的clicked()函数运行正常,但我无法实现shift单击功能。有没有人知道如何使两种功能都有效?我点击的功能本质上是一个缩放功能,顺便接收数据。
答案 0 :(得分:0)
如果我
.on("click", clicked);
我的clicked()函数运行正常,但我无法实现shift单击功能。
为什么不呢?当然可以。只需检查clicked
函数内的转换。
这是一个基本演示:
var circles = d3.select("svg")
.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
.attr("r", 20)
.attr("cy", 50)
.attr("cx", function(d) {
return 50 + 100 * d
})
.style("fill", "darkgray")
.style("stroke", "black")
.style("cursor", "pointer")
.on("click", clicked);
function clicked() {
if (d3.event.shiftKey) {
d3.select(this).style("fill", "steelblue");
}
console.log("This is the clicked function")
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
为了完整性,这是您的第一个代码段的问题:当您使用selection.on附加侦听器时,
将为元素评估指定的侦听器,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(nodes [i])
但是,在您的情况下,您只是将数据传递给clicked
函数:
clicked(d);
因此,clicked
函数对this
的引用不正确,这将是window。请查看以下代码段:
var circles = d3.select("svg")
.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
.attr("r", 20)
.attr("cy", 50)
.attr("cx", function(d) {
return 50 + 100 * d
})
.style("fill", "darkgray")
.style("stroke", "black")
.style("cursor", "pointer")
.on("click", function(d){
clicked(d)
});
function clicked(datum) {
console.log("The datum is: " + datum);
console.log("'this' is: " + this)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
一个简单的解决方法是保留对this
:
var circles = d3.select("svg")
.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
.attr("r", 20)
.attr("cy", 50)
.attr("cx", function(d) {
return 50 + 100 * d
})
.style("fill", "darkgray")
.style("stroke", "black")
.style("cursor", "pointer")
.on("click", function(d) {
var self = this;
clicked(d, self)
});
function clicked(datum, thisElement) {
console.log("The datum is: " + datum);
console.log("'this' is: " + thisElement)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
或使用Function.prototype.call(由@DavidKnipe建议):
var circles = d3.select("svg")
.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
.attr("r", 20)
.attr("cy", 50)
.attr("cx", function(d) {
return 50 + 100 * d
})
.style("fill", "darkgray")
.style("stroke", "black")
.style("cursor", "pointer")
.on("click", function(d) {
clicked.call(this, d);
});
function clicked(datum) {
console.log("The datum is: " + datum);
console.log("'this' is: " + this)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;