我正在尝试在 d3 中实现点击事件,但我也希望可以选择在同一个 svg 元素上移动点击以触发不同的功能。如果我单击该元素,我希望它调用我的 clicked() 函数,但如果我移动单击该元素,我希望它将其填充样式更改为“steelblue”。我正在尝试:
.on("click", function(d){
if (d3.event.shiftKey) {
d3.select(this).style("fill", "steelblue");
}
clicked(d);
})
但我只是从 d3 得到“Uncaught TypeError: t.getAttribute is not a function”,因为我假设我的 clicked() 函数没有被正确调用或传递参数。
如果我这样做:
.on("click", clicked);
我的 clicked() 函数运行良好,但我无法实现 shift click 功能。有谁知道让这两种功能都起作用的方法?我的点击功能本质上是一个缩放功能,顺便接受了数据 d。
最佳答案
If I do
.on("click", clicked);
my clicked() function works perfectly, but I have no way of implementing the shift click functionality.
为什么不呢?当然可以。只需检查 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>
为了完整起见,这是您的第一个代码段的问题:当您使用 selection.on 附加监听器时,
The specified listener will be evaluated for the element, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (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)
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
一个简单的解决方法是保留对 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)
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
或使用 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)
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
关于javascript - 在同一元素上实现 shift click 和 click 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48118536/