我正在尝试创建一个可重用的 D3 事件函数,该函数提供一些关于单击 + 双击的稍微丰富的事件。这个想法是双击不应该触发单击。我设法做到了这一点,但现在我引入了第三个方面(长按),基本行为似乎正在破坏,我不明白为什么。
var custom = { };
custom.events = function () {
var clickTimeout = 3000; // The timeout that is used to distinguish between a single and double click
var longClickTimeout = 1000; // The timeout that is used to identify a long press
var clickTimer; // The timer that is used for a single click event
var longTimer; // The timer for a long press
var dispatch = d3.dispatch("click", "dblclick", "longclick", "mousedown", "mouseup");
function events(g) {
g.on("mousedown", mousedown)
.on("mouseup", mouseup)
.on("click", clicked)
.on("dblclick", doubleClicked);
};
/**
* Function that's called when an item is clicked. This function
* handles the advanced behaviour and farms out calls for both single
* and double click style events
* @params {object} d - The D3 datum
* @aparams {number} i - The index of the datum
*/
function clicked(d, i) {
if (d3.event.defaultPrevented) return; // Ignore if a drag operation is taking place
d3.event.stopPropagation(); // Prevent the event going any further
// If we already have a timer then we need to execute
// a double click behaviour event
console.log("Click Timer : " + clickTimer);
if (clickTimer) {
console.log("Clearing Click Timer : " + clickTimer);
clearTimeout(clickTimer);
clickTimer = null;
dispatch.dblclick.call(this, d, i);
return;
}
// Setup the timer for single click
clickTimer = setTimeout(function () {
// Trigger a single click
clickTimer = null;
dispatch.click.call(this, d, i);
}, clickTimeout);
console.log("Creating Click Timer : " + clickTimer);
};
/*
* Function that's called when an item is double clicked. In
* this case the function is just suppressed
*/
function doubleClicked(d, i) {
// Suppress the natural double click event
d3.event.stopPropagation();
};
function mousedown(d, i) {
// Set up the long press timer
longTimer = setTimeout(function () {
longClickTimeout = null;
dispatch.longclick.call(this, d, i);
}, longClickTimeout);
console.log("Creating Long Timer : " + longTimer);
// Trigger a mouse down event
dispatch.mousedown.call(this, d, i);
}
function mouseup(d, i) {
// Cancel the long timer (it should have already fired if it needed to)
if (longTimer) {
console.log("Clearing Long Timer : " + longTimer);
clearTimeout(longTimer);
clickTimer = null;
}
dispatch.mouseup.call(this, d, i);
}
// Return the bound events
return d3.rebind(events, dispatch, "on");
};
var events = custom.events()
.on("click", function() { console.log("click"); })
.on("dblclick", function() { console.log("dblclick"); });
d3.select("svg")
.append("circle")
.attr("r", 150)
.attr("cx", 150)
.attr("cy", 150)
.style("fill", "red")
.call(events);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="500"></svg>
您可以在上面的代码片段中看到我所整理的内容,以及我的调试输出。如果您尝试在控制台可见的情况下双击圆圈,即使双击,似乎 clickTimer
也始终为 null。
但是,如果您注释掉第 13 行和 上 mousedown
或 mouseup
的 on
注册>14 分别:
g.on("mousedown", mousedown)
.on("mouseup", mouseup)
.on("click", clicked)
.on("dblclick", doubleClicked);
然后一切都按预期工作,但是我似乎无法发现这两个功能的任何副作用。我在这里遗漏了一些明显的东西吗?
最佳答案
您在检查 longTimer
的 mouseup
处理程序中将 clickTimer
设置为 null
。纠正该行为即可修复该行为。
关于javascript - 当 mousedown/mouseup 注册时,双击计时器始终为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28588871/